mirror of https://github.com/GNOME/gimp.git
Again modified the formatting stuff. Some preliminary header stuff.
Soon moving to use cpp..
This commit is contained in:
parent
b593a1592f
commit
51b4b0966e
|
@ -1,3 +1,8 @@
|
|||
1998-11-20 Lauri Alanko <la@iki.fi>
|
||||
|
||||
* Again modified the formatting stuff. Some preliminary header
|
||||
stuff. Soon moving to use cpp..
|
||||
|
||||
1998-11-18 Lauri Alanko <la@iki.fi>
|
||||
|
||||
* Signal marshalling should be pretty complete now. Demarshalling
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
noinst_PROGRAMS = gcg
|
||||
|
||||
|
||||
CFLAGS=-I/usr/local/lib/glib/include -DYYDEBUG=1 -g -Wall -W -DCPP="$(CPP)"
|
||||
INCLUDES = -DYYDEBUG=1 @GLIB_CFLAGS@
|
||||
CFLAGS=-g -Wall -W -DCPP="$(CPP)" -ansi -pedantic
|
||||
INCLUDES = @GLIB_CFLAGS@
|
||||
YFLAGS = -d -v 2>/dev/null
|
||||
LIBS = @GLIB_LIBS@
|
||||
|
||||
|
|
|
@ -1,72 +1,47 @@
|
|||
#include "gcg.h"
|
||||
|
||||
|
||||
static GHashTable* module_hash;
|
||||
static GHashTable* package_hash = NULL;
|
||||
static GSList* def_list = NULL;
|
||||
|
||||
|
||||
void init_db(void){
|
||||
module_hash=g_hash_table_new(NULL, NULL);
|
||||
package_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=TYPE_INVALID;
|
||||
p->decl_header=NULL;
|
||||
p->def_header=NULL;
|
||||
p->definition=NULL;
|
||||
g_hash_table_insert(m->decl_hash, name, p);
|
||||
PrimType* get_type(Package* pkg, Id name){
|
||||
return g_hash_table_lookup(pkg->type_hash, name);
|
||||
}
|
||||
return p;
|
||||
|
||||
void put_type(PrimType* t){
|
||||
g_hash_table_insert(t->module->package->type_hash,
|
||||
(gpointer)t->name, t);
|
||||
}
|
||||
|
||||
void put_def(Def* d){
|
||||
PrimType* t=d->type;
|
||||
g_assert(t);
|
||||
t->definition=d;
|
||||
def_list = g_slist_append (def_list, d);
|
||||
}
|
||||
|
||||
Def* get_def(Id modname, Id type){
|
||||
PrimType* t=get_type(modname, type);
|
||||
g_assert(t);
|
||||
return t->definition;
|
||||
Package* get_pkg(Id pkgname){
|
||||
return g_hash_table_lookup(package_hash, pkgname);
|
||||
}
|
||||
|
||||
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;
|
||||
void put_pkg(Package* pkg){
|
||||
g_hash_table_insert(package_hash, (gpointer)pkg->name, pkg);
|
||||
}
|
||||
|
||||
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);
|
||||
Module* get_mod(Package* pkg, Id modname){
|
||||
return g_hash_table_lookup(pkg->mod_hash, modname);
|
||||
}
|
||||
|
||||
|
||||
void dfe_foo(gpointer key, gpointer p, gpointer dfed){
|
||||
Module* m=p;
|
||||
g_hash_table_foreach(m->decl_hash, dfe_bar, dfed);
|
||||
void put_mod(Module* m){
|
||||
g_hash_table_insert(m->package->mod_hash, (gpointer)m->name, m);
|
||||
}
|
||||
|
||||
void foreach_def(DefFunc f, gpointer user_data){
|
||||
DFEdata d={f,user_data};
|
||||
g_hash_table_foreach(module_hash, dfe_foo, &d);
|
||||
};
|
||||
|
||||
GSList* l = def_list;
|
||||
while(l){
|
||||
f(l->data, user_data);
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,17 @@
|
|||
#include "parser.h"
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
|
||||
#define __USE_POSIX2
|
||||
|
||||
#include <unistd.h>
|
||||
#include "output.h"
|
||||
|
||||
#ifndef CPP
|
||||
#define CPP "cpp"
|
||||
#endif
|
||||
|
||||
|
||||
Type* type_gtk_type;
|
||||
|
||||
Id func_hdr_name;
|
||||
|
@ -54,11 +62,6 @@ void output_cb(Def* def, gpointer out){
|
|||
int main(int argc, char* argv[]){
|
||||
/* target=stdout;*/
|
||||
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;
|
||||
init_db();
|
||||
|
@ -67,23 +70,20 @@ int main(int argc, char* argv[]){
|
|||
yyin=fopen(argv[optind], "r");
|
||||
g_assert(yyin);
|
||||
yyparse();
|
||||
type_gtk_type=g_new(Type, 1);
|
||||
type_gtk_type->is_const=FALSE;
|
||||
type_gtk_type->indirection=0;
|
||||
type_gtk_type->notnull=FALSE;
|
||||
type_gtk_type->prim=get_type(GET_ID("Gtk"), GET_ID("Type"));
|
||||
g_assert(type_gtk_type->prim);
|
||||
|
||||
foreach_def(output_cb, out);
|
||||
f=fopen(type_hdr_name, "w+");
|
||||
pr_write(out, f, &tag_type, 1);
|
||||
pr_write(out, f, "type");
|
||||
f=fopen(source_name, "w+");
|
||||
pr_write(out, f, &tag_source_head, 1);
|
||||
pr_write(out, f, &tag_source, 1);
|
||||
pr_write(out, f, "source_deps");
|
||||
pr_write(out, f, "source_head");
|
||||
pr_write(out, f, "source");
|
||||
f=fopen(func_hdr_name, "w+");
|
||||
pr_write(out, f, &tag_functions, 1);
|
||||
pr_write(out, f, "func_deps");
|
||||
pr_write(out, f, "functions");
|
||||
f=fopen(prot_hdr_name, "w+");
|
||||
pr_write(out, f, &tag_protected, 1);
|
||||
pr_write(out, f, "prot_deps");
|
||||
pr_write(out, f, "protected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ typedef struct _MemberClass MemberClass;
|
|||
typedef struct _DefClass DefClass;
|
||||
typedef struct _Param Param;
|
||||
typedef struct _Module Module;
|
||||
typedef struct _Package Package;
|
||||
|
||||
typedef enum{
|
||||
TYPE_INVALID,
|
||||
|
@ -36,19 +37,23 @@ typedef enum{
|
|||
TYPE_OBJECT
|
||||
} TypeKind;
|
||||
|
||||
struct _Module {
|
||||
struct _Package {
|
||||
Id name;
|
||||
Id common_header;
|
||||
GHashTable* decl_hash;
|
||||
GHashTable* type_hash;
|
||||
GHashTable* mod_hash;
|
||||
};
|
||||
|
||||
struct _Module {
|
||||
Package* package;
|
||||
Id name;
|
||||
Id header;
|
||||
};
|
||||
|
||||
|
||||
struct _PrimType {
|
||||
Module* module;
|
||||
Id name;
|
||||
TypeKind kind;
|
||||
Id decl_header;
|
||||
Id def_header;
|
||||
Def* definition;
|
||||
};
|
||||
|
||||
struct _Type {
|
||||
|
@ -114,7 +119,7 @@ typedef enum _EmitDef{
|
|||
|
||||
typedef enum _MemberType{
|
||||
MEMBER_DATA,
|
||||
MEMBER_METHOD,
|
||||
MEMBER_METHOD
|
||||
} MemberType;
|
||||
|
||||
typedef enum _DataMemberKind{
|
||||
|
@ -168,18 +173,14 @@ typedef void (*DefFunc)(Def* def, gpointer user_data);
|
|||
|
||||
|
||||
void init_db(void);
|
||||
void put_decl(PrimType* t);
|
||||
|
||||
PrimType* get_type(Package* pkg, Id type);
|
||||
void put_type(PrimType* t);
|
||||
Package* get_pkg(Id pkgname);
|
||||
void put_pkg(Package* pkg);
|
||||
Module* get_mod(Package* pkg, Id module);
|
||||
void put_mod(Module* m);
|
||||
void put_def(Def* d);
|
||||
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;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,42 +1,21 @@
|
|||
// this is just a simple test input file
|
||||
|
||||
module g {
|
||||
@int int;
|
||||
};
|
||||
#include <gimp.gh>
|
||||
|
||||
module Gtk {
|
||||
@int Type;
|
||||
};
|
||||
|
||||
module Gimp{
|
||||
class Object;
|
||||
class Layer;
|
||||
class Drawable;
|
||||
class Image;
|
||||
enum ImageType;
|
||||
enum ChannelType;
|
||||
enum BaseType;
|
||||
};
|
||||
module Gimp.Image;
|
||||
import g;
|
||||
|
||||
|
||||
module Gimp;
|
||||
|
||||
enum ImageType{
|
||||
rgb, rgba, gray, graya, indexed, indexeda
|
||||
};
|
||||
enum ChannelType{
|
||||
red, green, blue, gray, indexed, auxillary
|
||||
};
|
||||
enum BaseType{
|
||||
rgb, gray, indexed
|
||||
};
|
||||
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 int width;
|
||||
read-only int height;
|
||||
int num-cols;
|
||||
read-only BaseType base-type;
|
||||
read-write g.int foobar;
|
||||
read-write int foobar;
|
||||
read-write Layer& active-layer;
|
||||
read-write Layer* floating-sel;
|
||||
public static Image* new(g.int width,
|
||||
|
@ -52,7 +31,7 @@ class Image : Object{
|
|||
g.int a2,
|
||||
g.int a3,
|
||||
g.int a4,
|
||||
g.int a5,
|
||||
int a5,
|
||||
g.int a6,
|
||||
g.int a7,
|
||||
g.int a8,
|
||||
|
@ -61,4 +40,4 @@ g.int a10,
|
|||
g.int a11,
|
||||
g.int a12,
|
||||
g.int a13);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
%option noyywrap
|
||||
%option yylineno
|
||||
|
||||
%{
|
||||
#include "gcg.h"
|
||||
#include "parser.h"
|
||||
%}
|
||||
|
||||
|
||||
ident [A-Za-z][A-Za-z0-9-]*
|
||||
header <[[:alnum:]/.]+>
|
||||
ws [ \n\t\r]
|
||||
|
@ -20,6 +22,7 @@ static return T_STATIC;
|
|||
protected return T_PROTECTED;
|
||||
pre-emit return T_PRE_EMIT;
|
||||
post-emit return T_POST_EMIT;
|
||||
mid-emit return T_DUAL_EMIT;
|
||||
read-only return T_READ_ONLY;
|
||||
read-write return T_READ_WRITE;
|
||||
private return T_PRIVATE;
|
||||
|
@ -32,6 +35,7 @@ module return T_MODULE;
|
|||
import return T_IMPORT;
|
||||
header return T_HEADER;
|
||||
opaque return T_OPAQUE;
|
||||
package return T_PACKAGE;
|
||||
|
||||
void return T_VOID;
|
||||
enum return T_ENUM;
|
||||
|
@ -39,6 +43,7 @@ flags return T_FLAGS;
|
|||
@int return T_INT;
|
||||
real return T_DOUBLE;
|
||||
boxed return T_BOXED;
|
||||
foreign return T_FOREIGN;
|
||||
|
||||
|
||||
{ident} {
|
||||
|
@ -56,7 +61,9 @@ boxed return T_BOXED;
|
|||
}
|
||||
|
||||
{header} {
|
||||
yylval.id=g_quark_to_string(g_quark_from_string(yytext));
|
||||
gchar* tmp = g_strndup(&yytext[1], yyleng-2);
|
||||
yylval.id=g_quark_to_string(g_quark_from_string(tmp));
|
||||
g_free (tmp);
|
||||
return T_HEADERNAME;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ MarshallType marshalling_type(Type* t){
|
|||
SignalType* sig_type(Method* m){
|
||||
SignalType *t=g_new(SignalType, 1);
|
||||
GSList* p=m->params, *a=NULL;
|
||||
t->package = DEF(MEMBER(m)->my_class)->type->module->name;
|
||||
t->package = DEF(MEMBER(m)->my_class)->type->module->package->name;
|
||||
t->rettype = marshalling_type(&m->ret_type);
|
||||
while(p){
|
||||
Param* param=p->data;
|
||||
|
@ -152,7 +152,7 @@ PNode* p_handler_type(SignalType* t){
|
|||
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->module->package->name),
|
||||
p_c_ident(t->name),
|
||||
p_c_ident(MEMBER(s)->name));
|
||||
}
|
||||
|
@ -219,7 +219,8 @@ PNode* p_demarshaller(SignalType* t){
|
|||
gint idx=0;
|
||||
|
||||
|
||||
return p_lst((t->rettype==TYPE_NONE)
|
||||
return p_fmt("~~",
|
||||
(t->rettype==TYPE_NONE)
|
||||
? p_fmt("\t*(GTK_RETLOC_~(args[~])) =\n",
|
||||
p_gtype_name(t->rettype, FALSE),
|
||||
p_prf("%d", g_slist_length(t->argtypes)))
|
||||
|
@ -228,8 +229,7 @@ PNode* p_demarshaller(SignalType* t){
|
|||
"~"
|
||||
"\tuser_data);\n",
|
||||
p_cast(p_handler_type(t), p_str("func")),
|
||||
p_for(t->argtypes, p_arg_demarsh, &idx)),
|
||||
p_nil);
|
||||
p_for(t->argtypes, p_arg_demarsh, &idx)));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,18 +39,41 @@ PNode* p_c_macro(Id id){
|
|||
}
|
||||
|
||||
PNode* p_param(FunParams* p, ParamOptions* opt){
|
||||
return p_lst(opt->first ? p_nil : p_str(", "),
|
||||
return p_fmt("~~~~",
|
||||
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->name : p_nil,
|
||||
NULL);
|
||||
opt->names ? p->name : p_nil);
|
||||
}
|
||||
|
||||
PNode* p_prot_header(Module* m){
|
||||
if(m->header)
|
||||
return p_str(m->header);
|
||||
else
|
||||
return p_fmt("~/~_p.h",
|
||||
p_c_ident(m->package->name),
|
||||
p_c_ident(m->name));
|
||||
}
|
||||
|
||||
PNode* p_type_header(Module* m){
|
||||
if(m->header)
|
||||
return p_str(m->header);
|
||||
else
|
||||
return p_fmt("~/~_t.h",
|
||||
p_c_ident(m->package->name),
|
||||
p_c_ident(m->name));
|
||||
}
|
||||
|
||||
PNode* p_type_include(Module* m){
|
||||
return p_fmt("#include <~>\n",
|
||||
p_type_header(m));
|
||||
}
|
||||
|
||||
PNode* p_params(FunParams* args, ParamOptions* opt){
|
||||
ParamOptions o=*opt;
|
||||
PNode* n=p_nil;
|
||||
while(args){
|
||||
n=p_lst(n, p_param(args, &o), NULL);
|
||||
n=p_fmt("~~", n, p_param(args, &o));
|
||||
args=args->next;
|
||||
o.first=FALSE;
|
||||
}
|
||||
|
@ -68,9 +91,9 @@ PNode* p_prim_varname(PrimType* t){
|
|||
}
|
||||
|
||||
PNode* p_primtype(PrimType* t){
|
||||
return p_lst(p_str(t->module->name),
|
||||
p_str(t->name),
|
||||
NULL);
|
||||
return p_fmt("~~",
|
||||
p_str(t->module->package->name),
|
||||
p_str(t->name));
|
||||
}
|
||||
|
||||
PNode* p_cast(PNode* force_type, PNode* expression){
|
||||
|
@ -87,7 +110,7 @@ PNode* p_type(Type* t){
|
|||
t->is_const ? p_str("const ") : p_nil,
|
||||
p_primtype(t->prim));
|
||||
while(i--)
|
||||
node=p_lst(node, p_str("*"), NULL);
|
||||
node=p_fmt("~~", node, p_str("*"));
|
||||
/* file_add_dep(s, t->prim->decl_header);*/
|
||||
return node;
|
||||
}else
|
||||
|
@ -102,7 +125,7 @@ PNode* p_self_type(ObjectDef* o, PBool const_self){
|
|||
|
||||
PNode* p_varname(PrimType* t, PNode* name){
|
||||
return p_fmt("~_~_~",
|
||||
p_c_ident(t->module->name),
|
||||
p_c_ident(t->module->package->name),
|
||||
p_c_ident(t->name),
|
||||
name);
|
||||
}
|
||||
|
@ -125,8 +148,8 @@ PNode* p_type_guard(Type* t, PNode* var){
|
|||
|
||||
kind !=
|
||||
*/
|
||||
return p_lst
|
||||
((t->indirection && t->notnull
|
||||
return p_fmt("~~",
|
||||
(t->indirection && t->notnull
|
||||
? p_fmt("\tg_assert (~);\n", var)
|
||||
: p_nil),
|
||||
((t->indirection==1 && p->kind == TYPE_OBJECT)
|
||||
|
@ -148,14 +171,13 @@ PNode* p_type_guard(Type* t, PNode* var){
|
|||
var,
|
||||
p_macro_name(p, NULL, "LAST"))
|
||||
: p_nil))
|
||||
: p_nil)),
|
||||
NULL);
|
||||
: p_nil)));
|
||||
}
|
||||
|
||||
PNode* p_type_guards(FunParams* args){
|
||||
PNode* p=p_nil;
|
||||
while(args){
|
||||
p=p_lst(p, p_type_guard(&args->type, args->name), NULL);
|
||||
p=p_fmt("~~", p, p_type_guard(&args->type, args->name));
|
||||
args=args->next;
|
||||
}
|
||||
return p;
|
||||
|
@ -164,7 +186,11 @@ PNode* p_type_guards(FunParams* args){
|
|||
PNode* p_prototype(Type* rettype, PNode* name,
|
||||
PNode* args1,
|
||||
FunParams* args2){
|
||||
ParamOptions o={(!args1 || args1==p_nil), TRUE, TRUE};
|
||||
ParamOptions o;
|
||||
o.first = !args1 || args1 == p_nil;
|
||||
o.names = TRUE;
|
||||
o.types = TRUE;
|
||||
|
||||
return p_fmt("~ ~ (~~)",
|
||||
p_type(rettype),
|
||||
name,
|
||||
|
@ -176,14 +202,14 @@ void output_var_alias(PRoot* out, PrimType* t, PNode* basename){
|
|||
pr_add(out, "import_alias",
|
||||
p_fmt("#define ~ ~_~\n",
|
||||
basename,
|
||||
p_c_ident(t->module->name),
|
||||
p_c_ident(t->module->package->name),
|
||||
basename));
|
||||
}
|
||||
|
||||
void output_type_alias(PRoot* out, PrimType* t, PNode* basename){
|
||||
pr_add(out, "import_alias",
|
||||
p_fmt("typedef ~~ ~;\n",
|
||||
p_str(t->module->name),
|
||||
p_str(t->module->package->name),
|
||||
basename,
|
||||
basename));
|
||||
}
|
||||
|
@ -218,10 +244,10 @@ void output_func(PRoot* out,
|
|||
|
||||
PNode* p_macro_name(PrimType* t, Id mid, Id post){
|
||||
return p_fmt("~~_~~",
|
||||
p_c_macro(t->module->name),
|
||||
mid ? p_lst(p_str("_"), p_c_macro(mid), NULL) : p_nil,
|
||||
p_c_macro(t->module->package->name),
|
||||
mid ? p_fmt("_~", p_c_macro(mid)) : p_nil,
|
||||
p_c_macro(t->name),
|
||||
post ? p_lst(p_str("_"), p_c_macro(post), NULL) : p_nil);
|
||||
post ? p_fmt("_~", p_c_macro(post)) : p_nil);
|
||||
}
|
||||
|
||||
void output_var(PRoot* out, Id tag, PNode* type, PNode* name){
|
||||
|
@ -247,11 +273,11 @@ void output_def(PRoot* out, Def* d){
|
|||
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",
|
||||
" (~ ? ~() : (void)0, ~)\n",
|
||||
p_macro_name(t, "TYPE", NULL),
|
||||
type_var,
|
||||
type_var,
|
||||
p_internal_varname(t, p_str("init_type"))));
|
||||
p_internal_varname(t, p_str("init_type")),
|
||||
type_var));
|
||||
output_var(out, "type",
|
||||
p_str("GtkType"),
|
||||
type_var);
|
||||
|
@ -271,3 +297,13 @@ void output_def(PRoot* out, Def* d){
|
|||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void add_dep(PRoot* out, Id tag, PrimType* type){
|
||||
pr_put(out, tag, type->module);
|
||||
}
|
||||
|
||||
PNode* p_deps(Id tag){
|
||||
return p_col(tag, p_dep, NULL);
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -58,6 +58,8 @@ PNode* p_guard_end(const gchar *c);
|
|||
|
||||
PNode* p_c_ident(Id id);
|
||||
PNode* p_c_macro(Id id);
|
||||
PNode* p_prot_header(Module* m);
|
||||
PNode* p_type_header(Module* m);
|
||||
|
||||
|
||||
void output_func(PRoot* out,
|
||||
|
@ -71,8 +73,11 @@ void output_func(PRoot* out,
|
|||
|
||||
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);
|
||||
void output_object(PRoot* out, Def* d);
|
||||
void output_enum(PRoot* out, Def* d);
|
||||
void output_flags(PRoot* out, Def* d);
|
||||
PNode* p_type_include(Module* m);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,7 @@ void output_enum_type_init(PRoot* out, EnumDef* e){
|
|||
PrimType* t=DEF(e)->type;
|
||||
output_func(out,
|
||||
"type",
|
||||
type_gtk_type,
|
||||
NULL,
|
||||
p_internal_varname(t, p_str("init_type")),
|
||||
p_nil,
|
||||
NULL,
|
||||
|
@ -39,8 +39,7 @@ void output_enum_type_init(PRoot* out, EnumDef* e){
|
|||
"~"
|
||||
"\t\t{0, NULL, NULL}\n"
|
||||
"\t};\n"
|
||||
"\t~ = gtk_type_register_enum (\"~\", values);\n"
|
||||
"\treturn ~;\n",
|
||||
"\t~ = gtk_type_register_enum (\"~\", values);\n",
|
||||
p_prf("%d", g_slist_length(e->alternatives)+1),
|
||||
p_for(e->alternatives, p_enum_value, t),
|
||||
p_internal_varname(t, p_str("type")),
|
||||
|
@ -48,7 +47,8 @@ void output_enum_type_init(PRoot* out, EnumDef* e){
|
|||
p_internal_varname(t, p_str("type"))));
|
||||
}
|
||||
|
||||
void output_enum(PRoot* out, EnumDef* e){
|
||||
void output_enum(PRoot* out, Def* d){
|
||||
EnumDef* e = (EnumDef*)d;
|
||||
output_enum_type_init(out, e);
|
||||
pr_add(out, "type", p_enum_decl(e));
|
||||
}
|
||||
|
|
|
@ -13,10 +13,9 @@ PNode* p_flags_member(Id id, FlagData* d){
|
|||
}
|
||||
|
||||
PNode* p_flags_decl(FlagsDef* e){
|
||||
FlagData d={
|
||||
-1,
|
||||
DEF(e)->type
|
||||
};
|
||||
FlagData d;
|
||||
d.i = -1;
|
||||
d.t = DEF(e)->type;
|
||||
return p_fmt("typedef enum {\n"
|
||||
"~"
|
||||
"} ~;\n"
|
||||
|
@ -49,8 +48,7 @@ void output_flags_type_init(PRoot* out, FlagsDef* e){
|
|||
"~"
|
||||
"\t\t{0, NULL, NULL}\n"
|
||||
"\t};\n"
|
||||
"\t~ = gtk_type_register_flags (\"~\", values);\n"
|
||||
"\treturn ~;\n",
|
||||
"\t~ = gtk_type_register_flags (\"~\", values);\n",
|
||||
p_prf("%d", g_slist_length(e->flags)+1),
|
||||
p_for(e->flags, p_flags_value, t),
|
||||
p_internal_varname(t, p_str("type")),
|
||||
|
@ -58,8 +56,9 @@ void output_flags_type_init(PRoot* out, FlagsDef* e){
|
|||
p_internal_varname(t, p_str("type"))));
|
||||
}
|
||||
|
||||
void output_flags(PRoot* out, FlagsDef* e){
|
||||
pr_add(out, "type", p_flags_decl(e));
|
||||
output_flags_type_init(out, e);
|
||||
void output_flags(PRoot* out, Def* d){
|
||||
FlagsDef* f = (FlagsDef*) d;
|
||||
pr_add(out, "type", p_flags_decl(f));
|
||||
output_flags_type_init(out, f);
|
||||
}
|
||||
|
||||
|
|
|
@ -130,6 +130,11 @@ void output_connector(PRoot* out, Method* m){
|
|||
p_str(MEMBER(m)->name)));
|
||||
}
|
||||
|
||||
PNode* p_param_marshtype(gpointer p){
|
||||
Param* param=p;
|
||||
return p_fmt(",\n\t\t~",
|
||||
p_gtktype(¶m->type));
|
||||
}
|
||||
|
||||
|
||||
void output_method(PRoot* out, Method* m){
|
||||
|
@ -148,6 +153,7 @@ void output_method(PRoot* out, Method* m){
|
|||
p_self_name(MEMBER(m)),
|
||||
p_nil,
|
||||
m->params);
|
||||
|
||||
switch(k){
|
||||
SignalType* sig;
|
||||
case METH_EMIT_PRE:
|
||||
|
@ -155,10 +161,43 @@ void output_method(PRoot* out, Method* m){
|
|||
case METH_EMIT_BOTH:
|
||||
sig=sig_type(m);
|
||||
output_var(out, NULL,
|
||||
p_str("GtkSignalID"),
|
||||
p_str("guint"),
|
||||
p_signal_id(m));
|
||||
o.names=FALSE;
|
||||
o.types=TRUE;
|
||||
pr_put(out, "class_init_head",
|
||||
p_fmt("\textern void ~ (GtkObject*, GtkSignalFunc, "
|
||||
"gpointer, GtkArg*);\n",
|
||||
p_signal_demarshaller_name(sig)));
|
||||
pr_put(out, "member_class_init",
|
||||
p_fmt("\t~ =\n"
|
||||
"\tgtk_signal_new(\"~\",\n"
|
||||
"\t\tGTK_RUN_~,\n"
|
||||
"\t\tobklass->type,\n"
|
||||
"\t\tGTK_SIGNAL_OFFSET (~, ~),\n"
|
||||
"\t\t~,\n"
|
||||
"\t\t~,\n"
|
||||
"\t\t~"
|
||||
"~);\n"
|
||||
"\tgtk_object_class_add_signals(obklass,\n"
|
||||
"\t\t&~,\n"
|
||||
"\t\t1);\n"
|
||||
"\t}\n",
|
||||
p_signal_id(m),
|
||||
p_str(MEMBER(m)->name),
|
||||
p_str(m->kind==METH_EMIT_PRE
|
||||
?"FIRST"
|
||||
:m->kind==METH_EMIT_POST
|
||||
?"LAST"
|
||||
:"BOTH"),
|
||||
p_class_name(t),
|
||||
name,
|
||||
p_signal_demarshaller_name(sig),
|
||||
p_gtktype(&m->ret_type),
|
||||
p_prf("%d", g_slist_length(m->params)),
|
||||
p_for(m->params, p_param_marshtype, p_nil),
|
||||
p_signal_id(m)));
|
||||
|
||||
pr_add(out, "functions",
|
||||
p_fmt("typedef ~ (*~)(~, gpointer);\n",
|
||||
p_type(&m->ret_type),
|
||||
|
@ -174,16 +213,18 @@ void output_method(PRoot* out, Method* m){
|
|||
o.names=TRUE;
|
||||
o.types=TRUE;
|
||||
pr_add(out, "source_head",
|
||||
p_fmt("static inline ~ ~ (~);\n",
|
||||
p_fmt("static ~ ~_~_real (~);\n",
|
||||
p_type(&m->ret_type),
|
||||
p_real_varname(t, name),
|
||||
p_c_ident(t->name),
|
||||
name,
|
||||
p_params(par, &o)));
|
||||
o.types=FALSE;
|
||||
dispatch=p_fmt("\t~ ~(~);\n",
|
||||
dispatch=p_fmt("\t~~_~_real (~);\n",
|
||||
m->ret_type.prim?
|
||||
p_str("return "):
|
||||
p_nil,
|
||||
p_real_varname(t, name),
|
||||
p_c_ident(t->name),
|
||||
name,
|
||||
p_params(par, &o));
|
||||
break;
|
||||
case METH_VIRTUAL:
|
||||
|
@ -262,6 +303,7 @@ void output_data_member(PRoot* out, DataMember* m){
|
|||
}
|
||||
/* fall through */
|
||||
case DATA_READONLY:
|
||||
pr_put(out, "func_depends", m->type.prim->module);
|
||||
par=fparams("t", &MEMBER(m)->my_class->self_type[TRUE],
|
||||
self,
|
||||
p_nil);
|
||||
|
@ -275,7 +317,9 @@ void output_data_member(PRoot* out, DataMember* m){
|
|||
self,
|
||||
name));
|
||||
fparams_free(par);
|
||||
/* fall through */
|
||||
case DATA_PROTECTED:
|
||||
pr_put(out, "prot_depends", m->type.prim->module);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,7 +351,7 @@ void output_object_type_init(PRoot* out, ObjectDef* o){
|
|||
PNode* type_var=p_internal_varname(t, p_str("type"));
|
||||
output_func(out,
|
||||
"type",
|
||||
type_gtk_type,
|
||||
NULL,
|
||||
p_internal_varname(t, p_str("init_type")),
|
||||
p_nil,
|
||||
NULL,
|
||||
|
@ -322,8 +366,7 @@ void output_object_type_init(PRoot* out, ObjectDef* o){
|
|||
"\t\tNULL,\n"
|
||||
"\t};\n"
|
||||
"\tif (!~)\n"
|
||||
"\t\t~ = gtk_type_unique (~, &info);\n"
|
||||
"\treturn ~;\n",
|
||||
"\t\t~ = gtk_type_unique (~, &info);\n",
|
||||
p_primtype(t),
|
||||
p_primtype(t),
|
||||
p_class_name(t),
|
||||
|
@ -335,67 +378,12 @@ void output_object_type_init(PRoot* out, ObjectDef* o){
|
|||
type_var));
|
||||
}
|
||||
|
||||
PNode* p_param_marshtype(gpointer p){
|
||||
Param* param=p;
|
||||
return p_fmt(",\n\t\t~",
|
||||
p_gtktype(¶m->type));
|
||||
}
|
||||
|
||||
PNode* p_member_class_init(gpointer m, gpointer o){
|
||||
ObjectDef* ob=o;
|
||||
Member* mem=m;
|
||||
Method* meth;
|
||||
SignalType* sig;
|
||||
if(mem->membertype!=MEMBER_METHOD)
|
||||
return p_nil;
|
||||
meth=m;
|
||||
sig=sig_type(meth);
|
||||
switch(meth->kind){
|
||||
case METH_EMIT_PRE:
|
||||
case METH_EMIT_POST:
|
||||
case METH_EMIT_BOTH:
|
||||
return p_fmt("\t{\n"
|
||||
"\textern void ~ (GtkObject*, GtkSignalFunc, "
|
||||
"gpointer, GtkArg*);\n"
|
||||
"\t~ =\n"
|
||||
"\tgtk_signal_new(\"~\",\n"
|
||||
"\t\tGTK_RUN_~,\n"
|
||||
"\t\tobklass->type,\n"
|
||||
"\t\tGTK_SIGNAL_OFFSET (~, ~),\n"
|
||||
"\t\t~,\n"
|
||||
"\t\t~,\n"
|
||||
"\t\t~"
|
||||
"~);\n"
|
||||
"\tgtk_object_class_add_signals(obklass,\n"
|
||||
"\t\t&~,\n"
|
||||
"\t\t1);\n"
|
||||
"\t}\n",
|
||||
p_signal_demarshaller_name(sig),
|
||||
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(sig),
|
||||
p_gtktype(&meth->ret_type),
|
||||
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;
|
||||
}
|
||||
sig_type_free(sig);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void output_object_init(PRoot* out, ObjectDef* o){
|
||||
pr_add(out, "prot_deps",
|
||||
p_col("prot_depends", p_type_include));
|
||||
pr_add(out, "func_deps",
|
||||
p_col("func_depends", p_type_include));
|
||||
pr_add(out, "source_head",
|
||||
p_fmt("static inline void ~ (~ ~);\n",
|
||||
p_varname(DEF(o)->type, p_str("init_real")),
|
||||
|
@ -424,15 +412,18 @@ void output_class_init(PRoot* out, ObjectDef* o){
|
|||
p_fmt("~* klass",
|
||||
p_class_name(DEF(o)->type)),
|
||||
NULL,
|
||||
p_fmt("\tGtkObjectClass* obklass = \n"
|
||||
"\t\t(GtkObjectClass*) klass;\n"
|
||||
p_fmt("\tGtkObjectClass* obklass = "
|
||||
"(GtkObjectClass*) klass;\n"
|
||||
"~"
|
||||
"~"
|
||||
"\t~ (klass);\n",
|
||||
p_for(o->members, p_member_class_init, o),
|
||||
p_col("class_init_head", NULL),
|
||||
p_col("member_class_init", NULL),
|
||||
p_varname(DEF(o)->type, p_str("class_init_real"))));
|
||||
}
|
||||
|
||||
void output_object(PRoot* out, ObjectDef* o){
|
||||
void output_object(PRoot* out, Def* d){
|
||||
ObjectDef* o = (ObjectDef*)d;
|
||||
output_object_type_init(out, o);
|
||||
output_class_init(out, o);
|
||||
output_object_init(out, o);
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
#include "gcg.h"
|
||||
#define YYDEBUG 1
|
||||
|
||||
static Package* current_package;
|
||||
static Module* current_module;
|
||||
static Id current_header;
|
||||
static ObjectDef* current_class;
|
||||
static GSList* imports;
|
||||
static Method* current_method;
|
||||
|
||||
static GSList* imports_list;
|
||||
|
@ -70,12 +69,15 @@ static GSList* imports_list;
|
|||
%token T_DOUBLE
|
||||
%token T_BOXED
|
||||
%token T_SIGNAL
|
||||
%token T_FOREIGN
|
||||
%token T_PACKAGE
|
||||
|
||||
%token<id> T_IDENT
|
||||
%token<id> T_HEADERNAME
|
||||
%token<str> T_STRING
|
||||
|
||||
%type<id> ident
|
||||
%type<id> headerdef
|
||||
%type<fund_type> fundtype
|
||||
%type<type> type
|
||||
%type<type> typeorvoid
|
||||
|
@ -108,28 +110,74 @@ start_symbol: deffile ;
|
|||
|
||||
deffile: declarations definitions;
|
||||
|
||||
declarations: /* empty */ | declarations modulescope;
|
||||
declarations: /* empty */ | declarations package;
|
||||
|
||||
definitions: current_module_def deflist;
|
||||
|
||||
deflist: /* empty */ | deflist def {
|
||||
put_def($2);
|
||||
};
|
||||
} | deflist import;
|
||||
|
||||
import: T_IMPORT ident T_END {
|
||||
imports=g_slist_prepend(imports, (gpointer)($2));
|
||||
import: T_IMPORT importlist T_END;
|
||||
|
||||
importlist: ident {
|
||||
Package* p = get_pkg($1);
|
||||
if(!p)
|
||||
g_error("Attempt to import unknown package %s", $1);
|
||||
imports_list = g_slist_prepend(imports_list, p);
|
||||
} | importlist T_COMMA ident {
|
||||
Package* p = get_pkg($3);
|
||||
if(!p)
|
||||
g_error("Attempt to import unknown package %s", $3);
|
||||
imports_list = g_slist_prepend(imports_list, p);
|
||||
}
|
||||
|
||||
modulescope: T_MODULE ident T_OPEN_B {
|
||||
current_module=get_mod($2);
|
||||
} decllist T_CLOSE_B {
|
||||
current_module=NULL;
|
||||
} T_END;
|
||||
|
||||
current_module_def: T_MODULE ident T_END {
|
||||
current_module=get_mod($2);
|
||||
package: T_PACKAGE ident T_OPEN_B {
|
||||
Package* p = get_pkg($2);
|
||||
if(!p){
|
||||
p = g_new(Package, 1);
|
||||
p->name = $2;
|
||||
p->type_hash = g_hash_table_new(NULL, NULL);
|
||||
p->mod_hash = g_hash_table_new(NULL, NULL);
|
||||
put_pkg(p);
|
||||
}
|
||||
current_package = p;
|
||||
} modulelist T_CLOSE_B {
|
||||
current_package = NULL;
|
||||
};
|
||||
|
||||
current_module_def: T_MODULE ident T_SCOPE ident T_END {
|
||||
Package* p = get_pkg($2);
|
||||
Module* m;
|
||||
if(!p)
|
||||
g_error("Unknown package %s", $2);
|
||||
m = get_mod(p, $4);
|
||||
if(!m)
|
||||
g_error("Unknown module %s.%s", $2, $4);
|
||||
current_module = m;
|
||||
}
|
||||
|
||||
|
||||
modulelist: /* empty */ | modulelist module;
|
||||
|
||||
headerdef: /* empty */ {
|
||||
$$ = NULL;
|
||||
}| T_HEADERNAME;
|
||||
|
||||
|
||||
|
||||
module: T_MODULE ident headerdef T_OPEN_B {
|
||||
Module* m = get_mod(current_package, $2);
|
||||
if(!m){
|
||||
m = g_new(Module, 1);
|
||||
m->package = current_package;
|
||||
m->name = $2;
|
||||
m->header = $3;
|
||||
put_mod(m);
|
||||
}
|
||||
current_module = m;
|
||||
} decllist T_CLOSE_B;
|
||||
|
||||
decllist: /* empty */ | decllist decl;
|
||||
|
||||
decl: simpledecl ;/* | classdecl | opaquedecl | protclassdecl;*/
|
||||
|
@ -148,9 +196,12 @@ fundtype: T_INT {
|
|||
$$ = TYPE_FLAGS;
|
||||
}
|
||||
|
||||
simpledecl: fundtype primtype T_END {
|
||||
g_assert($2->kind==TYPE_INVALID);
|
||||
$2->kind = $1;
|
||||
simpledecl: fundtype ident T_END {
|
||||
PrimType* t = g_new(PrimType, 1);
|
||||
t->module = current_module;
|
||||
t->name = $2;
|
||||
t->kind = $1;
|
||||
put_type(t);
|
||||
};
|
||||
|
||||
semitype: const_def primtype {
|
||||
|
@ -181,9 +232,26 @@ typeorvoid: type | T_VOID {
|
|||
|
||||
|
||||
primtype: ident T_SCOPE ident {
|
||||
$$ = get_type($1, $3);
|
||||
Package* p=get_pkg($1);
|
||||
PrimType* t;
|
||||
if(!p)
|
||||
g_error("Unknown package %s!", $1);
|
||||
t = get_type(p, $3);
|
||||
if(!t)
|
||||
g_error("Unknown type %s:%s", $1, $3);
|
||||
$$ = t;
|
||||
} | ident {
|
||||
$$ = get_type(current_module->name, $1);
|
||||
Package* p = current_module->package;
|
||||
PrimType* t;
|
||||
GSList* l = imports_list;
|
||||
t = get_type(p, $1);
|
||||
while(l && !t){
|
||||
t = get_type(l->data, $1);
|
||||
l = l->next;
|
||||
}
|
||||
if(!t)
|
||||
g_error("Couldn't find type %s in import list", $1);
|
||||
$$ = t;
|
||||
};
|
||||
|
||||
paramlist: /* empty */ {
|
||||
|
@ -271,22 +339,22 @@ idlist: ident {
|
|||
|
||||
def: classdef | enumdef | flagsdef;
|
||||
|
||||
enumdef: T_ENUM primtype T_OPEN_B idlist T_CLOSE_B docstring T_END {
|
||||
enumdef: T_ENUM primtype docstring T_OPEN_B idlist T_CLOSE_B {
|
||||
EnumDef* d=g_new(EnumDef, 1);
|
||||
g_assert($2->kind==TYPE_ENUM);
|
||||
d->alternatives = $4;
|
||||
d->alternatives = $5;
|
||||
$$=DEF(d);
|
||||
$$->type=$2;
|
||||
$$->doc=$6;
|
||||
$$->doc=$3;
|
||||
};
|
||||
|
||||
flagsdef: T_FLAGS primtype T_OPEN_B idlist T_CLOSE_B docstring T_END {
|
||||
flagsdef: T_FLAGS primtype docstring T_OPEN_B idlist T_CLOSE_B T_END {
|
||||
FlagsDef* d=g_new(FlagsDef, 1);
|
||||
g_assert($2->kind==TYPE_ENUM);
|
||||
d->flags = $4;
|
||||
d->flags = $5;
|
||||
$$=DEF(d);
|
||||
$$->type=$2;
|
||||
$$->doc=$6;
|
||||
$$->doc=$3;
|
||||
};
|
||||
|
||||
parent: /* empty */{
|
||||
|
@ -298,9 +366,14 @@ parent: /* empty */{
|
|||
classdef: T_CLASS primtype parent docstring T_OPEN_B {
|
||||
g_assert($2->kind==TYPE_OBJECT);
|
||||
g_assert(!$3 || $3->kind==TYPE_OBJECT);
|
||||
g_assert($2->module == current_module);
|
||||
current_class=g_new(ObjectDef, 1);
|
||||
} classbody T_CLOSE_B T_END {
|
||||
Type t={FALSE, 1, TRUE, $2};
|
||||
} classbody T_CLOSE_B {
|
||||
Type t;
|
||||
t.is_const = FALSE;
|
||||
t.indirection = 1;
|
||||
t.notnull = TRUE;
|
||||
t.prim = $2;
|
||||
current_class->self_type[0]=t;
|
||||
t.is_const=TRUE;
|
||||
current_class->self_type[1]=t;
|
||||
|
|
|
@ -2,36 +2,67 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
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))
|
||||
|
||||
#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;
|
||||
|
||||
typedef enum{
|
||||
NODE_NIL,
|
||||
NODE_DATA,
|
||||
NODE_COLLECT
|
||||
} PNodeType;
|
||||
|
||||
typedef struct{
|
||||
gchar* str;
|
||||
PNode* node;
|
||||
} PBlock;
|
||||
|
||||
typedef struct _PRNode{
|
||||
GQuark tag;
|
||||
PNode* node;
|
||||
} PRNode;
|
||||
|
||||
|
||||
struct _PRoot{
|
||||
GData* data;
|
||||
GList* nodes;
|
||||
};
|
||||
|
||||
struct _PNode{
|
||||
gconstpointer magic;
|
||||
guint ref_count;
|
||||
GList* float_link;
|
||||
const gchar* str;
|
||||
GSList* children;
|
||||
PNodeType type;
|
||||
union {
|
||||
struct {
|
||||
gint nblocks;
|
||||
PBlock* blocks;
|
||||
} b;
|
||||
struct {
|
||||
PNodeCreateFunc func;
|
||||
GQuark tag;
|
||||
} c;
|
||||
} u;
|
||||
};
|
||||
|
||||
static PNode p_nil_node = {
|
||||
&p_node_magic_tag,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
NODE_NIL,
|
||||
{{0,NULL}}
|
||||
};
|
||||
|
||||
PNode* p_nil = &p_nil_node;
|
||||
|
||||
static PNode* p_make(void){
|
||||
static PNode* p_make(PNodeType type){
|
||||
PNode* node;
|
||||
if(!p_node_chunk)
|
||||
p_node_chunk = g_mem_chunk_create(PNode, 1024,
|
||||
|
@ -41,8 +72,7 @@ static PNode* p_make(void){
|
|||
node->ref_count = 0;
|
||||
node->magic = &p_node_magic_tag;
|
||||
node->float_link = p_float_list = g_list_prepend(p_float_list, node);
|
||||
node->str = NULL;
|
||||
node->children = NULL;
|
||||
node->type = type;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -65,55 +95,86 @@ void p_unref(PNode* node){
|
|||
node->ref_count--;
|
||||
if(node->ref_count>0)
|
||||
return;
|
||||
else{
|
||||
GSList* l;
|
||||
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);
|
||||
switch(node->type){
|
||||
case NODE_DATA:{
|
||||
PBlock* bl = node->u.b.blocks;
|
||||
gint i=node->u.b.nblocks;
|
||||
while(i--){
|
||||
g_free(bl[i].str);
|
||||
p_unref(bl[i].node);
|
||||
}
|
||||
g_free(bl);
|
||||
break;
|
||||
}
|
||||
case NODE_NIL:
|
||||
break;
|
||||
case NODE_COLLECT:
|
||||
break;
|
||||
}
|
||||
g_mem_chunk_free(p_node_chunk, node);
|
||||
}
|
||||
}
|
||||
|
||||
void p_write(PNode* node, FILE* f){
|
||||
GSList* l;
|
||||
BE_NODE(node);
|
||||
if(node==p_nil)
|
||||
return;
|
||||
l = node->children;
|
||||
if(l){
|
||||
const gchar* c = node->str;
|
||||
if(c)
|
||||
while(*c){
|
||||
gint i = 0;
|
||||
while(c[i] && c[i] != '~')
|
||||
i++;
|
||||
fwrite(c, i, 1, f);
|
||||
c += i;
|
||||
if(*c == '~'){
|
||||
c++;
|
||||
g_assert(l);
|
||||
p_write(l->data, f);
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
typedef struct{
|
||||
FILE* f;
|
||||
PRoot* p;
|
||||
} PWrite;
|
||||
|
||||
typedef struct{
|
||||
PWrite* w;
|
||||
PNode* n;
|
||||
} PCollect;
|
||||
|
||||
static void p_write(PNode* node, PWrite* w);
|
||||
|
||||
|
||||
void cb_pwrite(gpointer key, gpointer value, gpointer data){
|
||||
PCollect* c = data;
|
||||
PNodeCreateFunc func = c->n->u.c.func;
|
||||
(void)key;
|
||||
if(func)
|
||||
p_write(func(value), c->w);
|
||||
else
|
||||
do{
|
||||
p_write(l->data, f);
|
||||
}while((l=l->next));
|
||||
}else if(node->str)
|
||||
fputs(node->str, f);
|
||||
p_write(value, c->w);
|
||||
}
|
||||
|
||||
void p_traverse(PNode* node, PNodeTraverseFunc func, gpointer user_data){
|
||||
GSList* l;
|
||||
|
||||
static void p_write(PNode* node, PWrite* w){
|
||||
BE_NODE(node);
|
||||
func(node, user_data);
|
||||
for(l=node->children;l;l=l->next)
|
||||
p_traverse(l->data, func, user_data);
|
||||
switch(node->type){
|
||||
case NODE_DATA:{
|
||||
gint i = 0, n = node->u.b.nblocks;
|
||||
PBlock* bl = node->u.b.blocks;
|
||||
|
||||
for(i = 0; i < n; i++){
|
||||
if(bl[i].str)
|
||||
fputs(bl[i].str, w->f);
|
||||
p_write(bl[i].node, w);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_NIL:
|
||||
break;
|
||||
case NODE_COLLECT:{
|
||||
GHashTable* h = g_datalist_id_get_data(&w->p->data,
|
||||
node->u.c.tag);
|
||||
PCollect c;
|
||||
c.w = w;
|
||||
c.n = node;
|
||||
if(!h)
|
||||
break;
|
||||
g_hash_table_foreach(h, cb_pwrite, &c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PNode* p_simple_string(gchar* str){
|
||||
PNode* n = p_make(NODE_DATA);
|
||||
n->u.b.nblocks = 1;
|
||||
n->u.b.blocks = g_new(PBlock, 1);
|
||||
n->u.b.blocks[0].str = str;
|
||||
n->u.b.blocks[0].node = p_nil;
|
||||
return n;
|
||||
}
|
||||
|
||||
PNode* p_str(const gchar* str){
|
||||
|
@ -122,74 +183,64 @@ PNode* p_str(const gchar* str){
|
|||
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);
|
||||
}
|
||||
if(n)
|
||||
return n;
|
||||
else
|
||||
return p_simple_string(g_strdup(str));
|
||||
}
|
||||
|
||||
PNode* p_prf(const gchar* format, ...){
|
||||
PNode* n = p_make();
|
||||
PNode* n;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
n->str = g_strdup_vprintf (format, args);
|
||||
n = p_simple_string(g_strdup_vprintf (format, args));
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
|
||||
PNode* p_fmt(const gchar* f, ...){
|
||||
va_list args;
|
||||
gchar* b = f;
|
||||
PNode* n;
|
||||
GSList* l = NULL;
|
||||
const gchar* b;
|
||||
PNode* n = p_make(NODE_DATA);
|
||||
gint i;
|
||||
PBlock* bl;
|
||||
|
||||
va_start(args, f);
|
||||
g_assert(f);
|
||||
while(*f){
|
||||
while(*f && *f != '~')
|
||||
f++;
|
||||
if(*f == '~'){
|
||||
PNode* p;
|
||||
for(b = f, i = 0; *b; b++)
|
||||
if(*b == '~')
|
||||
i++;
|
||||
if(b!=f && b[-1] != '~')
|
||||
i++;
|
||||
bl = g_new(PBlock, i);
|
||||
n->u.b.blocks = bl;
|
||||
n->u.b.nblocks = i;
|
||||
|
||||
for(b = f, i = 0; *b; i++){
|
||||
gint idx=0;
|
||||
PNode* p = p_nil;
|
||||
while(b[idx] && b[idx] != '~')
|
||||
idx++;
|
||||
bl[i].str = g_strndup(b, idx);
|
||||
if(b[idx] == '~'){
|
||||
p = va_arg(args, PNode*);
|
||||
BE_NODE(p);
|
||||
if(p!=p_nil)
|
||||
p_ref(p);
|
||||
l = g_slist_prepend(l, p);
|
||||
|
||||
f++;
|
||||
idx++;
|
||||
}
|
||||
bl[i].node = p;
|
||||
b = &b[idx];
|
||||
}
|
||||
if(!l)
|
||||
return p_str(f);
|
||||
n = p_make();
|
||||
n->str = g_strdup(b);
|
||||
n->children = g_slist_reverse(l);
|
||||
return n;
|
||||
}
|
||||
|
||||
PNode* p_lst(PNode* n, ...){
|
||||
va_list args;
|
||||
GSList* l = NULL;
|
||||
PNode* node;
|
||||
g_assert(n);
|
||||
va_start(args, n);
|
||||
while(n){
|
||||
BE_NODE(n);
|
||||
if(n!=p_nil){
|
||||
p_ref(n);
|
||||
l = g_slist_prepend(l, n);
|
||||
}
|
||||
n = va_arg(args, PNode*);
|
||||
}
|
||||
node = p_make();
|
||||
node->children = g_slist_reverse(l);
|
||||
return node;
|
||||
}
|
||||
|
||||
PNode* p_for(GSList* l, PNodeCreateFunc func, gpointer user_data){
|
||||
PNode* n = p_make();
|
||||
GSList* lst = NULL;
|
||||
n->str = NULL;
|
||||
PNode* p_for(GSList* lst, PNodeCreateFunc func, gpointer user_data){
|
||||
PNode* n = p_make(NODE_DATA);
|
||||
GSList* l = lst;
|
||||
gint i = g_slist_length(l);
|
||||
n->u.b.nblocks = i;
|
||||
n->u.b.blocks = g_new(PBlock, i);
|
||||
i = 0;
|
||||
while(l){
|
||||
PNode* p;
|
||||
if(user_data == p_nil)
|
||||
|
@ -197,30 +248,25 @@ PNode* p_for(GSList* l, PNodeCreateFunc func, gpointer user_data){
|
|||
else
|
||||
p = func(l->data, user_data);
|
||||
BE_NODE(p);
|
||||
if(p!=p_nil){
|
||||
p_ref(p);
|
||||
lst=g_slist_prepend(lst, p);
|
||||
}
|
||||
n->u.b.blocks[i].str = NULL;
|
||||
n->u.b.blocks[i++].node = p;
|
||||
l = l->next;
|
||||
}
|
||||
n->children=g_slist_reverse(lst);
|
||||
return n;
|
||||
}
|
||||
|
||||
typedef struct _PRNode{
|
||||
GQuark tag;
|
||||
PNode* node;
|
||||
} PRNode;
|
||||
|
||||
|
||||
struct _PRoot{
|
||||
GList* nodes;
|
||||
};
|
||||
|
||||
PNode* p_col(const gchar* tag, PNodeCreateFunc func){
|
||||
PNode* n = p_make(NODE_COLLECT);
|
||||
n->u.c.func = func;
|
||||
n->u.c.tag = g_quark_from_string(tag);
|
||||
return n;
|
||||
}
|
||||
|
||||
PRoot* pr_new(void){
|
||||
PRoot* pr = g_new(PRoot, 1);
|
||||
pr->nodes = NULL;
|
||||
g_datalist_init(&pr->data);
|
||||
return pr;
|
||||
}
|
||||
|
||||
|
@ -237,27 +283,49 @@ void pr_add(PRoot* pr, const gchar* tag, PNode* node){
|
|||
p_ref(node);
|
||||
}
|
||||
|
||||
void pr_write(PRoot* pr, FILE* stream, const gchar** tags, gint n){
|
||||
GList* l;
|
||||
GQuark* quarks;
|
||||
gint i;
|
||||
void pr_put(PRoot* pr, const gchar* tag, gpointer datum){
|
||||
GHashTable* h = g_datalist_get_data(&pr->data, tag);
|
||||
if(!h){
|
||||
h = g_hash_table_new(NULL, NULL);
|
||||
g_datalist_set_data(&pr->data, tag, h);
|
||||
}
|
||||
|
||||
quarks=g_new(GQuark, n);
|
||||
for(i=0;i<n;i++)
|
||||
quarks[i]=g_quark_from_string(tags[i]);
|
||||
g_hash_table_insert(h, datum, datum);
|
||||
}
|
||||
|
||||
void pr_write(PRoot* pr, FILE* stream, const gchar* tag){
|
||||
GList* l;
|
||||
GQuark q;
|
||||
PWrite w;
|
||||
|
||||
g_assert(pr);
|
||||
|
||||
w.p = pr;
|
||||
w.f = stream;
|
||||
q = g_quark_from_string(tag);
|
||||
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);
|
||||
if(node->tag == q)
|
||||
p_write(node->node, &w);
|
||||
}
|
||||
}
|
||||
|
||||
gchar* pr_to_str(PRoot* pr, const gchar* tag){
|
||||
FILE* f = tmpfile();
|
||||
glong len;
|
||||
gchar* buf;
|
||||
pr_write(pr, f, tag);
|
||||
len = ftell(f);
|
||||
rewind(f);
|
||||
buf = g_new(gchar, len+1);
|
||||
fread(buf, len, 1, f);
|
||||
buf[len]='\0';
|
||||
fclose(f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pr_free(PRoot* pr){
|
||||
GList* l;
|
||||
for(l=pr->nodes;l;l = l->next){
|
||||
|
|
|
@ -13,19 +13,20 @@ typedef PNode* (*PNodeCreateFunc) ();
|
|||
|
||||
void p_ref(PNode* node);
|
||||
void p_unref(PNode* node);
|
||||
void p_write(PNode* node, FILE* f);
|
||||
PNode* p_str(const gchar* str);
|
||||
PNode* p_qrk(const gchar* str);
|
||||
PNode* p_prf(const gchar* format, ...) G_GNUC_PRINTF(1, 2);
|
||||
PNode* p_fmt(const gchar* f, ...);
|
||||
PNode* p_lst(PNode* n, ...);
|
||||
PNode* p_for(GSList* l, PNodeCreateFunc func, gpointer user_data);
|
||||
void p_traverse(PNode* node, PNodeTraverseFunc func, gpointer user_data);
|
||||
PNode* p_col(const gchar* tag, PNodeCreateFunc func);
|
||||
|
||||
PRoot* pr_new(void);
|
||||
void pr_add(PRoot* root, const gchar* tag, PNode* node);
|
||||
void pr_write(PRoot* pr, FILE* stream, const gchar** tags, gint n);
|
||||
void pr_put(PRoot* pr, const gchar* tag, gpointer datum);
|
||||
void pr_write(PRoot* pr, FILE* stream, const gchar* tag);
|
||||
void pr_free(PRoot* root);
|
||||
gchar* pr_to_str(PRoot* pr, const gchar* tags);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue