mirror of https://github.com/GNOME/gimp.git
It actually runs now, with a zillion caveats, but anyway..
Still have to do lotsa things for serious use..
This commit is contained in:
parent
51b4b0966e
commit
d74bf3623e
|
@ -1,3 +1,8 @@
|
|||
1998-11-21 Lauri Alanko <la@iki.fi>
|
||||
|
||||
* It actually runs now, with a zillion caveats, but anyway..
|
||||
Still have to do lotsa things for serious use..
|
||||
|
||||
1998-11-20 Lauri Alanko <la@iki.fi>
|
||||
|
||||
* Again modified the formatting stuff. Some preliminary header
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
noinst_PROGRAMS = gcg
|
||||
|
||||
CPP=cpp -nostdinc -I /usr/share/gcg -I /usr/local/share/gcg -I .
|
||||
|
||||
CFLAGS=-g -Wall -W -DCPP="$(CPP)" -ansi -pedantic
|
||||
CFLAGS=-g -Wall -W "-DCPP=\"$(CPP)\""
|
||||
INCLUDES = @GLIB_CFLAGS@
|
||||
YFLAGS = -d -v 2>/dev/null
|
||||
YFLAGS = -d -v
|
||||
LFLAGS = -d
|
||||
LIBS = @GLIB_LIBS@
|
||||
|
||||
lexer.c: $(srcdir)/lexer.l
|
||||
|
|
|
@ -2,7 +2,8 @@ AC_INIT(gcg.c)
|
|||
AM_INIT_AUTOMAKE(gcg, 0.1)
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_YACC
|
||||
AM_PROG_LEX
|
||||
AM_PATH_GLIB(1.0.0,,AC_ERROR(need at least Glib version 1.0))
|
||||
AC_OUTPUT(Makefile)
|
||||
AC_OUTPUT([Makefile ex/Makefile])
|
||||
|
|
|
@ -10,12 +10,16 @@ void init_db(void){
|
|||
}
|
||||
|
||||
PrimType* get_type(Package* pkg, Id name){
|
||||
return g_hash_table_lookup(pkg->type_hash, name);
|
||||
if(pkg)
|
||||
return g_hash_table_lookup(pkg->type_hash, name);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void put_type(PrimType* t){
|
||||
g_hash_table_insert(t->module->package->type_hash,
|
||||
(gpointer)t->name, t);
|
||||
if(t->module && t->module->package)
|
||||
g_hash_table_insert(t->module->package->type_hash,
|
||||
(gpointer)t->name, t);
|
||||
}
|
||||
|
||||
void put_def(Def* d){
|
||||
|
@ -31,11 +35,15 @@ void put_pkg(Package* pkg){
|
|||
}
|
||||
|
||||
Module* get_mod(Package* pkg, Id modname){
|
||||
return g_hash_table_lookup(pkg->mod_hash, modname);
|
||||
if(pkg)
|
||||
return g_hash_table_lookup(pkg->mod_hash, modname);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void put_mod(Module* m){
|
||||
g_hash_table_insert(m->package->mod_hash, (gpointer)m->name, m);
|
||||
if(m->package)
|
||||
g_hash_table_insert(m->package->mod_hash, (gpointer)m->name, m);
|
||||
}
|
||||
|
||||
void foreach_def(DefFunc f, gpointer user_data){
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
noinst_LIBRARIES = libgcgexample.a
|
||||
|
||||
CFLAGS=-g -Wall -W -I..
|
||||
|
||||
SUFFIXES = .gc .gh
|
||||
|
||||
EXTRA_DIST = stream.gh ostream.gc fileostream.gc
|
||||
|
||||
BUILT_SOURCES = \
|
||||
ostream_s.c ostream.h ostream_t.h ostream_p.h \
|
||||
file_ostream_s.c file_ostream.h file_ostream_t.h file_ostream_p.h
|
||||
|
||||
DEFS = ostream_s.c file_ostream_s.c
|
||||
|
||||
|
||||
$(DEFS): %_s.c: %.gc
|
||||
../gcg -o $@ -I ../gh $<
|
||||
|
||||
|
||||
libgcgexample_a_SOURCES = \
|
||||
ostream_s.c file_ostream_s.c
|
||||
|
|
@ -0,0 +1 @@
|
|||
This is just a bunch of miscellaneous test/example classes.
|
|
@ -0,0 +1,24 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static void ex_file_ostream_init_real(ExFileOstream* str){
|
||||
str->file = NULL;
|
||||
}
|
||||
|
||||
static void put_char(ExOstream* s, gchar c){
|
||||
ExFileOstream* str = EX_FILE_OSTREAM(s);
|
||||
fputc(c, str->file);
|
||||
}
|
||||
|
||||
static void ex_file_ostream_class_init_real(ExFileOstreamClass* klass){
|
||||
((ExOstreamClass*)klass)->putchar = put_char;
|
||||
}
|
||||
|
||||
static ExFileOstream* file_ostream_open_real(gchar* filename){
|
||||
ExFileOstream* str;
|
||||
FILE* f = fopen(filename, "w+");
|
||||
if(!f)
|
||||
return NULL;
|
||||
str = gtk_type_new(EX_TYPE_FILE_OSTREAM);
|
||||
str->file = f;
|
||||
return str;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#include "stream.gh"
|
||||
|
||||
package{
|
||||
module <stdio.h> {
|
||||
foreign FILE;
|
||||
}
|
||||
}
|
||||
|
||||
module Ex.FileOstream;
|
||||
|
||||
|
||||
class FileOstream : Ostream{
|
||||
.FILE* file;
|
||||
public static FileOstream* open(g.char* filename);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/* Aye, _mondo_ slow default method.. */
|
||||
|
||||
static void putstring(ExOstream* str, gchar* string){
|
||||
gint i;
|
||||
for(i = 0; string[i]; i++)
|
||||
ex_ostream_putchar(str, string[i]);
|
||||
}
|
||||
|
||||
|
||||
static void ex_ostream_init_real(ExOstream* str){
|
||||
}
|
||||
|
||||
static void ex_ostream_class_init_real(ExOstreamClass* klass){
|
||||
klass->putstring = putstring;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include <stream.gh>
|
||||
|
||||
module Ex.Ostream;
|
||||
import g;
|
||||
|
||||
|
||||
class Ostream {
|
||||
public virtual void putchar (char c);
|
||||
public virtual void putstring (char* str);
|
||||
public virtual void flush ();
|
||||
public virtual void close ();
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#include <gcg.gh>
|
||||
|
||||
package Ex {
|
||||
module Ostream{
|
||||
class Ostream;
|
||||
}
|
||||
module FileOstream{
|
||||
class FileOstream;
|
||||
}
|
||||
module StringOstream{
|
||||
class StringOstream;
|
||||
}
|
||||
}
|
||||
|
148
tools/gcg/gcg.c
148
tools/gcg/gcg.c
|
@ -1,10 +1,8 @@
|
|||
#include "gcg.h"
|
||||
#include "parser.h"
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
|
||||
#define __USE_POSIX2
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "gcg.h"
|
||||
#include "parse.h"
|
||||
#include <unistd.h>
|
||||
#include "output.h"
|
||||
|
||||
|
@ -12,41 +10,36 @@
|
|||
#define CPP "cpp"
|
||||
#endif
|
||||
|
||||
Id header_root = "..";
|
||||
Id source_name = NULL;
|
||||
Id impl_name = NULL;
|
||||
|
||||
Type* type_gtk_type;
|
||||
|
||||
Id func_hdr_name;
|
||||
Id type_hdr_name;
|
||||
Id prot_hdr_name;
|
||||
Id source_name;
|
||||
Id impl_name;
|
||||
extern int yydebug;
|
||||
extern FILE* yyin;
|
||||
|
||||
extern int yyparse(void);
|
||||
GString* cpp_cmd;
|
||||
|
||||
void get_options(int argc, char* argv[]){
|
||||
gint x=0;
|
||||
yydebug = yy_flex_debug = FALSE;
|
||||
do{
|
||||
x=getopt(argc, argv, "f:t:p:s:i:d");
|
||||
x=getopt(argc, argv, "D:i:dI:o:");
|
||||
switch(x){
|
||||
case 'f':
|
||||
func_hdr_name=optarg;
|
||||
case 'D':
|
||||
header_root=optarg;
|
||||
break;
|
||||
case 't':
|
||||
type_hdr_name=optarg;
|
||||
break;
|
||||
case 'p':
|
||||
prot_hdr_name=optarg;
|
||||
break;
|
||||
case 's':
|
||||
source_name=optarg;
|
||||
case 'I':
|
||||
g_string_append(cpp_cmd, " -I ");
|
||||
g_string_append(cpp_cmd, optarg);
|
||||
break;
|
||||
case 'i':
|
||||
impl_name=optarg;
|
||||
break;
|
||||
case 'd':
|
||||
yydebug=1;
|
||||
if(!yydebug)
|
||||
yydebug = TRUE;
|
||||
else
|
||||
yy_flex_debug = TRUE;
|
||||
break;
|
||||
case 'o':
|
||||
source_name = optarg;
|
||||
break;
|
||||
case '?':
|
||||
case ':':
|
||||
|
@ -59,31 +52,102 @@ void output_cb(Def* def, gpointer out){
|
|||
output_def(out, def);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void open_out(PNode*(*func)(Module*),
|
||||
Id suffix, PNode* n, PRoot* out){
|
||||
GString* s = g_string_new(header_root);
|
||||
gchar* str;
|
||||
PNode* guard;
|
||||
FILE* f;
|
||||
g_string_append(s, "/");
|
||||
str = p_to_str(func(current_module), NULL);
|
||||
g_string_append(s, str);
|
||||
g_free(str);
|
||||
f = fopen(s->str, "w+");
|
||||
if(!f)
|
||||
g_error("Unable to open file %s: %s",
|
||||
s->str,
|
||||
strerror(errno));
|
||||
g_string_free(s, TRUE);
|
||||
guard=p_fmt("_g_~_~_~",
|
||||
p_c_ident(current_module->package->name),
|
||||
p_c_ident(current_module->name),
|
||||
p_str(suffix));
|
||||
p_write(p_fmt("#ifndef ~\n"
|
||||
"#define ~\n"
|
||||
"~"
|
||||
"#endif /* ~ */\n",
|
||||
guard,
|
||||
guard,
|
||||
n,
|
||||
guard),
|
||||
f, out);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]){
|
||||
/* target=stdout;*/
|
||||
PRoot* out=pr_new();
|
||||
|
||||
FILE* f;
|
||||
|
||||
init_db();
|
||||
cpp_cmd = g_string_new(CPP);
|
||||
yydebug=0;
|
||||
get_options(argc, argv);
|
||||
yyin=fopen(argv[optind], "r");
|
||||
g_string_append(cpp_cmd, " ");
|
||||
g_string_append(cpp_cmd, argv[optind]);
|
||||
|
||||
|
||||
yyin=popen(cpp_cmd->str, "r");
|
||||
/*yyin=fopen(argv[optind], "r");*/
|
||||
g_assert(yyin);
|
||||
yyparse();
|
||||
|
||||
if(!impl_name)
|
||||
impl_name = p_to_str(p_fmt("~.c",
|
||||
p_c_ident(current_module->name)),
|
||||
NULL);
|
||||
if(!source_name)
|
||||
source_name = p_to_str(p_fmt("~_s.c",
|
||||
p_c_ident(current_module->name)),
|
||||
NULL);
|
||||
|
||||
foreach_def(output_cb, out);
|
||||
f=fopen(type_hdr_name, "w+");
|
||||
pr_write(out, f, "type");
|
||||
|
||||
f=fopen(source_name, "w+");
|
||||
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, "func_deps");
|
||||
pr_write(out, f, "functions");
|
||||
f=fopen(prot_hdr_name, "w+");
|
||||
pr_write(out, f, "prot_deps");
|
||||
pr_write(out, f, "protected");
|
||||
if(!f)
|
||||
g_error("Unable to open file %s: %s",
|
||||
source_name, strerror(errno));
|
||||
p_write(p_fmt("~~~"
|
||||
"#include \"~\"\n",
|
||||
p_col("source_prot_depends", p_prot_include),
|
||||
p_col("source_head", NULL),
|
||||
p_col("source", NULL),
|
||||
p_str(impl_name)),
|
||||
f, out);
|
||||
fclose(f);
|
||||
|
||||
|
||||
open_out(p_type_header, "type",
|
||||
p_fmt("#include <gtk/gtktypeutils.h>\n"
|
||||
"~",
|
||||
p_col("type", NULL)),
|
||||
out);
|
||||
|
||||
open_out(p_func_header, "funcs",
|
||||
p_fmt("~~~",
|
||||
p_col("func_parent_depends", p_func_include),
|
||||
p_col("func_depends", p_type_include),
|
||||
p_col("functions", NULL)),
|
||||
out);
|
||||
|
||||
open_out(p_prot_header, "prot",
|
||||
p_fmt("~~~",
|
||||
p_col("prot_parent_depends", p_prot_include),
|
||||
p_col("prot_depends", p_type_include),
|
||||
p_col("protected", NULL)),
|
||||
out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,11 +34,14 @@ typedef enum{
|
|||
TYPE_ENUM,
|
||||
TYPE_FLAGS,
|
||||
TYPE_FOREIGN,
|
||||
TYPE_OBJECT
|
||||
TYPE_OBJECT,
|
||||
TYPE_BOXED,
|
||||
TYPE_CHAR
|
||||
} TypeKind;
|
||||
|
||||
struct _Package {
|
||||
Id name;
|
||||
Id headerbase;
|
||||
GHashTable* type_hash;
|
||||
GHashTable* mod_hash;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
package Gtk{
|
||||
module <gtk/gtksignal.h>{
|
||||
class Object;
|
||||
}
|
||||
}
|
||||
|
||||
#include <glib.gh>
|
||||
|
||||
root Gtk.Object;
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package g {
|
||||
module <glib.h> {
|
||||
integer int;
|
||||
integer uint;
|
||||
integer boolean;
|
||||
character char;
|
||||
character uchar;
|
||||
}
|
||||
}
|
||||
|
||||
package G {
|
||||
module <glib.h> {
|
||||
boxed List;
|
||||
boxed SList;
|
||||
boxed HashTable;
|
||||
boxed String;
|
||||
boxed Array;
|
||||
boxed Cache;
|
||||
boxed Data;
|
||||
boxed Node;
|
||||
boxed Scanner;
|
||||
boxed ScannerConfig;
|
||||
boxed Relation;
|
||||
boxed MemChunk;
|
||||
boxed Hook;
|
||||
foreign Func;
|
||||
foreign HashFunc;
|
||||
foreign HFunc;
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// this is just a simple test input file
|
||||
|
||||
#include <gimp.gh>
|
||||
|
||||
module Gimp.Image;
|
||||
import g;
|
||||
|
||||
|
||||
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 int width;
|
||||
read-only int height;
|
||||
int num-cols;
|
||||
read-only BaseType base-type;
|
||||
read-write int foobar;
|
||||
read-write Layer& active-layer;
|
||||
read-write 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);
|
||||
protected pre-emit void foo-4(g.int x) const;
|
||||
public post-emit g.int foo-5(g.int x, Drawable**& n, Image* z);
|
||||
public post-emit g.int foo-6(g.int a1,
|
||||
g.int a2,
|
||||
g.int a3,
|
||||
g.int a4,
|
||||
int a5,
|
||||
g.int a6,
|
||||
g.int a7,
|
||||
g.int a8,
|
||||
g.int a9,
|
||||
g.int a10,
|
||||
g.int a11,
|
||||
g.int a12,
|
||||
g.int a13);
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
%{
|
||||
#include "gcg.h"
|
||||
#include "parser.h"
|
||||
#include "parse.h"
|
||||
%}
|
||||
|
||||
|
||||
|
@ -14,9 +15,10 @@ comment \/\/[^\n]*\n
|
|||
string \"(([^\"]*)|\\\"|\\\\)*\"
|
||||
preproc ^#.*\n
|
||||
|
||||
|
||||
|
||||
%%
|
||||
|
||||
class return T_CLASS;
|
||||
public return T_PUBLIC;
|
||||
static return T_STATIC;
|
||||
protected return T_PROTECTED;
|
||||
|
@ -27,7 +29,7 @@ read-only return T_READ_ONLY;
|
|||
read-write return T_READ_WRITE;
|
||||
private return T_PRIVATE;
|
||||
const return T_CONST;
|
||||
abstract return T_ABSTRACT;
|
||||
virtual return T_ABSTRACT;
|
||||
direct return T_DIRECT;
|
||||
type return T_TYPE;
|
||||
attribute return T_ATTRIBUTE;
|
||||
|
@ -36,15 +38,17 @@ import return T_IMPORT;
|
|||
header return T_HEADER;
|
||||
opaque return T_OPAQUE;
|
||||
package return T_PACKAGE;
|
||||
|
||||
void return T_VOID;
|
||||
root return T_ROOT;
|
||||
|
||||
class return T_CLASS;
|
||||
enum return T_ENUM;
|
||||
flags return T_FLAGS;
|
||||
@int return T_INT;
|
||||
real return T_DOUBLE;
|
||||
integer return T_INT;
|
||||
double return T_DOUBLE;
|
||||
boxed return T_BOXED;
|
||||
foreign return T_FOREIGN;
|
||||
|
||||
character return T_CHAR;
|
||||
|
||||
{ident} {
|
||||
yylval.id=g_quark_to_string(g_quark_from_string(yytext));
|
||||
|
|
|
@ -112,13 +112,22 @@ PNode* p_gtktype(Type* t){
|
|||
case TYPE_ENUM:
|
||||
case TYPE_FLAGS:
|
||||
return p_macro_name(t->prim, "TYPE", NULL);
|
||||
case TYPE_CHAR:
|
||||
return p_str("GTK_TYPE_CHAR");
|
||||
case TYPE_FOREIGN:
|
||||
g_error("Cannot marshall foreign type %s.%s!",
|
||||
t->prim->module->package->name,
|
||||
t->prim->name);
|
||||
return NULL;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
return p_str("GTK_TYPE_NONE");
|
||||
g_error("Cannot marshall type by value: %s.%s",
|
||||
t->prim->module->package->name,
|
||||
t->prim->name);
|
||||
return NULL;
|
||||
}
|
||||
}else if(t->indirection==1
|
||||
&& t->prim
|
||||
&& (t->prim->kind==TYPE_FOREIGN
|
||||
&& (t->prim->kind==TYPE_BOXED
|
||||
|| t->prim->kind==TYPE_OBJECT))
|
||||
return p_macro_name(t->prim, "TYPE", NULL);
|
||||
else
|
||||
|
|
|
@ -5,42 +5,41 @@
|
|||
|
||||
PNode* p_c_ident(Id id){
|
||||
PNode* n;
|
||||
gchar* c;
|
||||
gchar* s;
|
||||
gint i = 0;
|
||||
GString* s = g_string_new(NULL);
|
||||
|
||||
c=s=g_strdup(id);
|
||||
|
||||
while(*c){
|
||||
*c=tolower(*c);
|
||||
if(!isalnum(*c))
|
||||
*c='_';
|
||||
c++;
|
||||
for(i = 0; id[i]; i++){
|
||||
if(!isalnum(id[i]) || (i && isupper(id[i])))
|
||||
g_string_append_c(s, '_');
|
||||
if(isalnum(id[i]))
|
||||
g_string_append_c(s, tolower(id[i]));
|
||||
}
|
||||
n=p_str(s);
|
||||
g_free(s);
|
||||
n = p_str(s->str);
|
||||
g_string_free(s, TRUE);
|
||||
return n;
|
||||
}
|
||||
|
||||
PNode* p_c_macro(Id id){
|
||||
PNode* n;
|
||||
gchar* c;
|
||||
gchar* s;
|
||||
gint i = 0;
|
||||
GString* s = g_string_new(NULL);
|
||||
|
||||
c=s=g_strdup(id);
|
||||
while(*c){
|
||||
*c=toupper(*c);
|
||||
if(!isalnum(*c))
|
||||
*c='_';
|
||||
c++;
|
||||
for(i = 0; id[i]; i++){
|
||||
if(!isalnum(id[i]) || (i && isupper(id[i])))
|
||||
g_string_append_c(s, '_');
|
||||
if(isalnum(id[i]))
|
||||
g_string_append_c(s, toupper(id[i]));
|
||||
}
|
||||
n=p_str(s);
|
||||
g_free(s);
|
||||
n = p_str(s->str);
|
||||
g_string_free(s, TRUE);
|
||||
return n;
|
||||
}
|
||||
|
||||
PNode* p_param(FunParams* p, ParamOptions* opt){
|
||||
return p_fmt("~~~~",
|
||||
opt->first ? p_nil : p_str(", "),
|
||||
return p_fmt("~~~~~~",
|
||||
opt->first ? p_nil : p_str(","),
|
||||
!opt->first && !opt->types ? p_str(" ") : p_nil,
|
||||
opt->types ? p_str("\n\t") : p_nil,
|
||||
opt->types ? p_type(&p->type) : p_nil,
|
||||
opt->types && opt->names ? p_str(" ") : p_nil,
|
||||
opt->names ? p->name : p_nil);
|
||||
|
@ -51,7 +50,9 @@ PNode* p_prot_header(Module* m){
|
|||
return p_str(m->header);
|
||||
else
|
||||
return p_fmt("~/~_p.h",
|
||||
p_c_ident(m->package->name),
|
||||
m->package->headerbase
|
||||
? p_str(m->package->headerbase)
|
||||
: p_c_ident(m->package->name),
|
||||
p_c_ident(m->name));
|
||||
}
|
||||
|
||||
|
@ -60,7 +61,20 @@ PNode* p_type_header(Module* m){
|
|||
return p_str(m->header);
|
||||
else
|
||||
return p_fmt("~/~_t.h",
|
||||
p_c_ident(m->package->name),
|
||||
m->package->headerbase
|
||||
? p_str(m->package->headerbase)
|
||||
: p_c_ident(m->package->name),
|
||||
p_c_ident(m->name));
|
||||
}
|
||||
|
||||
PNode* p_func_header(Module* m){
|
||||
if(m->header)
|
||||
return p_str(m->header);
|
||||
else
|
||||
return p_fmt("~/~.h",
|
||||
m->package->headerbase
|
||||
? p_str(m->package->headerbase)
|
||||
: p_c_ident(m->package->name),
|
||||
p_c_ident(m->name));
|
||||
}
|
||||
|
||||
|
@ -69,6 +83,17 @@ PNode* p_type_include(Module* m){
|
|||
p_type_header(m));
|
||||
}
|
||||
|
||||
PNode* p_prot_include(Module* m){
|
||||
return p_fmt("#include <~>\n",
|
||||
p_prot_header(m));
|
||||
}
|
||||
|
||||
PNode* p_func_include(Module* m){
|
||||
return p_fmt("#include <~>\n",
|
||||
p_func_header(m));
|
||||
}
|
||||
|
||||
|
||||
PNode* p_params(FunParams* args, ParamOptions* opt){
|
||||
ParamOptions o=*opt;
|
||||
PNode* n=p_nil;
|
||||
|
@ -155,21 +180,21 @@ PNode* p_type_guard(Type* t, PNode* var){
|
|||
((t->indirection==1 && p->kind == TYPE_OBJECT)
|
||||
? (t->notnull
|
||||
? p_fmt("\tg_assert (~(~));\n",
|
||||
p_macro_name(p, "IS", NULL),
|
||||
p_macro_name(p, "is", NULL),
|
||||
var)
|
||||
: p_fmt("\tg_assert (!~ || ~(~));\n",
|
||||
var,
|
||||
p_macro_name(p, "IS", NULL),
|
||||
p_macro_name(p, "is", NULL),
|
||||
var))
|
||||
: (t->indirection==0
|
||||
? ((p->kind == TYPE_ENUM)
|
||||
? p_fmt("\tg_assert (~ <= ~);\n",
|
||||
var,
|
||||
p_macro_name(p, NULL, "LAST"))
|
||||
p_macro_name(p, NULL, "last"))
|
||||
: ((p->kind == TYPE_FLAGS)
|
||||
? p_fmt("\tg_assert ((~ << 1) < ~);\n",
|
||||
var,
|
||||
p_macro_name(p, NULL, "LAST"))
|
||||
p_macro_name(p, NULL, "last"))
|
||||
: p_nil))
|
||||
: p_nil)));
|
||||
}
|
||||
|
@ -199,7 +224,7 @@ PNode* p_prototype(Type* rettype, PNode* name,
|
|||
}
|
||||
|
||||
void output_var_alias(PRoot* out, PrimType* t, PNode* basename){
|
||||
pr_add(out, "import_alias",
|
||||
pr_put(out, "import_alias",
|
||||
p_fmt("#define ~ ~_~\n",
|
||||
basename,
|
||||
p_c_ident(t->module->package->name),
|
||||
|
@ -207,7 +232,7 @@ void output_var_alias(PRoot* out, PrimType* t, PNode* basename){
|
|||
}
|
||||
|
||||
void output_type_alias(PRoot* out, PrimType* t, PNode* basename){
|
||||
pr_add(out, "import_alias",
|
||||
pr_put(out, "import_alias",
|
||||
p_fmt("typedef ~~ ~;\n",
|
||||
p_str(t->module->package->name),
|
||||
basename,
|
||||
|
@ -222,13 +247,13 @@ void output_func(PRoot* out,
|
|||
PNode* args1,
|
||||
FunParams* args2,
|
||||
PNode* body){
|
||||
pr_add(out, tag ? tag : "source_head",
|
||||
pr_put(out, tag ? tag : "source_head",
|
||||
p_fmt("~~;\n",
|
||||
tag
|
||||
? p_nil
|
||||
: p_str("static "),
|
||||
p_prototype(rettype, name, args1, args2)));
|
||||
pr_add(out, "source",
|
||||
pr_put(out, "source",
|
||||
p_fmt("~~{\n"
|
||||
"~"
|
||||
"~"
|
||||
|
@ -252,11 +277,11 @@ PNode* p_macro_name(PrimType* t, Id mid, Id post){
|
|||
|
||||
void output_var(PRoot* out, Id tag, PNode* type, PNode* name){
|
||||
if(tag)
|
||||
pr_add(out, tag,
|
||||
pr_put(out, tag,
|
||||
p_fmt("extern ~ ~;\n",
|
||||
type,
|
||||
name));
|
||||
pr_add(out, "source_head",
|
||||
pr_put(out, "source_head",
|
||||
p_fmt("~~ ~;\n",
|
||||
tag?p_nil:p_str("static "),
|
||||
type,
|
||||
|
@ -268,13 +293,13 @@ void output_def(PRoot* out, Def* d){
|
|||
PNode* type_var=p_internal_varname(t, p_str("type"));
|
||||
|
||||
/* GTK_TYPE_FOO macro */
|
||||
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"
|
||||
pr_put(out, "type", p_str("\n\n"));
|
||||
pr_put(out, "source", p_str("\n"));
|
||||
pr_put(out, "protected", p_str("\n\n"));
|
||||
pr_put(out, "source_head", p_str("\n"));
|
||||
pr_put(out, "type", p_fmt("#define ~ \\\n"
|
||||
" (~ ? ~() : (void)0, ~)\n",
|
||||
p_macro_name(t, "TYPE", NULL),
|
||||
p_macro_name(t, "type", NULL),
|
||||
type_var,
|
||||
p_internal_varname(t, p_str("init_type")),
|
||||
type_var));
|
||||
|
|
|
@ -60,6 +60,8 @@ PNode* p_c_ident(Id id);
|
|||
PNode* p_c_macro(Id id);
|
||||
PNode* p_prot_header(Module* m);
|
||||
PNode* p_type_header(Module* m);
|
||||
PNode* p_func_header(Module* m);
|
||||
|
||||
|
||||
|
||||
void output_func(PRoot* out,
|
||||
|
@ -77,6 +79,10 @@ 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);
|
||||
PNode* p_prot_include(Module* m);
|
||||
PNode* p_func_include(Module* m);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ PNode* p_enum_decl(EnumDef* e){
|
|||
"\t~ = ~\n"
|
||||
"} ~;\n",
|
||||
p_for(e->alternatives, p_enum_member, t),
|
||||
p_macro_name(t, NULL, "LAST"),
|
||||
p_macro_name(t, NULL, "last"),
|
||||
p_macro_name(t, NULL,
|
||||
g_slist_last(e->alternatives)->data),
|
||||
p_primtype(t));
|
||||
|
@ -50,6 +50,6 @@ void output_enum_type_init(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));
|
||||
pr_put(out, "type", p_enum_decl(e));
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ PNode* p_flags_decl(FlagsDef* e){
|
|||
p_for(e->flags, p_flags_member, &d),
|
||||
p_primtype(d.t),
|
||||
p_primtype(d.t),
|
||||
p_macro_name(d.t, NULL, "LAST"),
|
||||
p_macro_name(d.t, NULL, "last"),
|
||||
p_macro_name(d.t, NULL, g_slist_last(e->flags)->data));
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ void output_flags_type_init(PRoot* out, FlagsDef* e){
|
|||
|
||||
void output_flags(PRoot* out, Def* d){
|
||||
FlagsDef* f = (FlagsDef*) d;
|
||||
pr_add(out, "type", p_flags_decl(f));
|
||||
pr_put(out, "type", p_flags_decl(f));
|
||||
output_flags_type_init(out, f);
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ void output_connector(PRoot* out, Method* m){
|
|||
p_varname(DEF(MEMBER(m)->my_class)->type,
|
||||
p_fmt("connect_~",
|
||||
p_c_ident(MEMBER(m)->name))),
|
||||
p_fmt("~ handler, gpointer user_data",
|
||||
p_fmt("\n\t~ handler,\n\tgpointer user_data",
|
||||
p_signal_handler_type(m)),
|
||||
par,
|
||||
p_fmt("\t~gtk_signal_connect((GtkObject*)~,\n"
|
||||
|
@ -198,8 +198,10 @@ void output_method(PRoot* out, Method* m){
|
|||
p_for(m->params, p_param_marshtype, p_nil),
|
||||
p_signal_id(m)));
|
||||
|
||||
pr_add(out, "functions",
|
||||
p_fmt("typedef ~ (*~)(~, gpointer);\n",
|
||||
pr_put(out, "functions",
|
||||
p_fmt("typedef ~ (*~)("
|
||||
"~,\n"
|
||||
"\tgpointer);\n",
|
||||
p_type(&m->ret_type),
|
||||
p_signal_handler_type(m),
|
||||
p_params(par, &o)));
|
||||
|
@ -212,7 +214,7 @@ void output_method(PRoot* out, Method* m){
|
|||
case METH_DIRECT:
|
||||
o.names=TRUE;
|
||||
o.types=TRUE;
|
||||
pr_add(out, "source_head",
|
||||
pr_put(out, "source_head",
|
||||
p_fmt("static ~ ~_~_real (~);\n",
|
||||
p_type(&m->ret_type),
|
||||
p_c_ident(t->name),
|
||||
|
@ -341,9 +343,13 @@ void output_member_cb(gpointer a, gpointer b){
|
|||
|
||||
PNode* p_class_macros(ObjectDef* o ){
|
||||
PrimType* t=DEF(o)->type;
|
||||
return p_fmt("#define ~(o) GTK_CHECK_TYPE(o, ~)\n",
|
||||
p_macro_name(t, "IS", NULL),
|
||||
p_macro_name(t, "TYPE", NULL));
|
||||
return p_fmt("#define ~(o) GTK_CHECK_TYPE(o, ~)\n"
|
||||
"#define ~(o) GTK_CHECK_CAST(o, ~, ~)\n",
|
||||
p_macro_name(t, "is", NULL),
|
||||
p_macro_name(t, "type", NULL),
|
||||
p_macro_name(t, NULL, NULL),
|
||||
p_macro_name(t, "type", NULL),
|
||||
p_primtype(t));
|
||||
}
|
||||
|
||||
void output_object_type_init(PRoot* out, ObjectDef* o){
|
||||
|
@ -374,17 +380,13 @@ void output_object_type_init(PRoot* out, ObjectDef* o){
|
|||
p_varname(t, p_str("init")),
|
||||
type_var,
|
||||
type_var,
|
||||
p_macro_name(o->parent, "TYPE", NULL),
|
||||
p_macro_name(o->parent, "type", NULL),
|
||||
type_var));
|
||||
}
|
||||
|
||||
|
||||
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",
|
||||
pr_put(out, "source_head",
|
||||
p_fmt("static inline void ~ (~ ~);\n",
|
||||
p_varname(DEF(o)->type, p_str("init_real")),
|
||||
p_type(&o->self_type[FALSE]),
|
||||
|
@ -402,7 +404,7 @@ void output_object_init(PRoot* out, ObjectDef* o){
|
|||
}
|
||||
|
||||
void output_class_init(PRoot* out, ObjectDef* o){
|
||||
pr_add(out, "source_head",
|
||||
pr_put(out, "source_head",
|
||||
p_fmt("static inline void ~ (~* klass);\n",
|
||||
p_varname(DEF(o)->type, p_str("class_init_real")),
|
||||
p_class_name(DEF(o)->type)));
|
||||
|
@ -414,6 +416,7 @@ void output_class_init(PRoot* out, ObjectDef* o){
|
|||
NULL,
|
||||
p_fmt("\tGtkObjectClass* obklass = "
|
||||
"(GtkObjectClass*) klass;\n"
|
||||
"\t(void) obklass;\n"
|
||||
"~"
|
||||
"~"
|
||||
"\t~ (klass);\n",
|
||||
|
@ -424,13 +427,17 @@ void output_class_init(PRoot* out, ObjectDef* o){
|
|||
|
||||
void output_object(PRoot* out, Def* d){
|
||||
ObjectDef* o = (ObjectDef*)d;
|
||||
pr_put(out, "func_parent_depends", o->parent->module);
|
||||
pr_put(out, "prot_depends", d->type->module);
|
||||
pr_put(out, "prot_parent_depends", o->parent->module);
|
||||
pr_put(out, "source_prot_depends", d->type->module);
|
||||
output_object_type_init(out, o);
|
||||
output_class_init(out, o);
|
||||
output_object_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, "type", p_class_macros(o));
|
||||
pr_add(out, "protected", p_object_body(o));
|
||||
pr_put(out, "protected", p_class_decl(o));
|
||||
pr_put(out, "protected", p_class_body(o));
|
||||
pr_put(out, "type", p_object_decl(o));
|
||||
pr_put(out, "type", p_class_macros(o));
|
||||
pr_put(out, "protected", p_object_body(o));
|
||||
g_slist_foreach(o->members, output_member_cb, out);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
%{
|
||||
#include "gcg.h"
|
||||
#include "parse.h"
|
||||
|
||||
#define YYDEBUG 1
|
||||
|
||||
static Package* current_package;
|
||||
static Module* current_module;
|
||||
Module* current_module;
|
||||
static ObjectDef* current_class;
|
||||
static Method* current_method;
|
||||
|
||||
static PrimType* root_class;
|
||||
static GSList* imports_list;
|
||||
|
||||
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
|
@ -71,11 +75,14 @@ static GSList* imports_list;
|
|||
%token T_SIGNAL
|
||||
%token T_FOREIGN
|
||||
%token T_PACKAGE
|
||||
%token T_ROOT
|
||||
%token T_CHAR
|
||||
|
||||
%token<id> T_IDENT
|
||||
%token<id> T_HEADERNAME
|
||||
%token<str> T_STRING
|
||||
|
||||
%type<id> maybeident
|
||||
%type<id> ident
|
||||
%type<id> headerdef
|
||||
%type<fund_type> fundtype
|
||||
|
@ -110,7 +117,17 @@ start_symbol: deffile ;
|
|||
|
||||
deffile: declarations definitions;
|
||||
|
||||
declarations: /* empty */ | declarations package;
|
||||
declarations: /* empty */ | declarations package | declarations rootdef;
|
||||
|
||||
|
||||
rootdef: T_ROOT primtype T_END {
|
||||
if($2->kind != TYPE_OBJECT)
|
||||
g_error("Bad root type: %s.%s",
|
||||
$2->module->package->name,
|
||||
$2->name);
|
||||
root_class = $2;
|
||||
};
|
||||
|
||||
|
||||
definitions: current_module_def deflist;
|
||||
|
||||
|
@ -132,13 +149,18 @@ importlist: ident {
|
|||
imports_list = g_slist_prepend(imports_list, p);
|
||||
}
|
||||
|
||||
package: T_PACKAGE ident T_OPEN_B {
|
||||
Package* p = get_pkg($2);
|
||||
package: T_PACKAGE maybeident headerdef T_OPEN_B {
|
||||
Package* p;
|
||||
Id i = $2;
|
||||
if(!i)
|
||||
i = GET_ID("");
|
||||
p = get_pkg(i);
|
||||
if(!p){
|
||||
p = g_new(Package, 1);
|
||||
p->name = $2;
|
||||
p->name = i;
|
||||
p->type_hash = g_hash_table_new(NULL, NULL);
|
||||
p->mod_hash = g_hash_table_new(NULL, NULL);
|
||||
p->headerbase = $3;
|
||||
put_pkg(p);
|
||||
}
|
||||
current_package = p;
|
||||
|
@ -165,8 +187,13 @@ headerdef: /* empty */ {
|
|||
}| T_HEADERNAME;
|
||||
|
||||
|
||||
maybeident: ident | /* empty */ {
|
||||
$$ = NULL;
|
||||
};
|
||||
|
||||
module: T_MODULE ident headerdef T_OPEN_B {
|
||||
|
||||
|
||||
module: T_MODULE maybeident headerdef T_OPEN_B {
|
||||
Module* m = get_mod(current_package, $2);
|
||||
if(!m){
|
||||
m = g_new(Module, 1);
|
||||
|
@ -186,15 +213,21 @@ fundtype: T_INT {
|
|||
$$ = TYPE_INT;
|
||||
} | T_DOUBLE {
|
||||
$$ = TYPE_DOUBLE;
|
||||
} | T_BOXED {
|
||||
$$ = TYPE_FOREIGN;
|
||||
} | T_CLASS {
|
||||
$$ = TYPE_OBJECT;
|
||||
} | T_ENUM {
|
||||
$$ = TYPE_ENUM;
|
||||
} | T_FLAGS {
|
||||
$$ = TYPE_FLAGS;
|
||||
}
|
||||
} | T_BOXED {
|
||||
$$ = TYPE_BOXED;
|
||||
} | T_FOREIGN {
|
||||
$$ = TYPE_FOREIGN;
|
||||
} | T_CHAR {
|
||||
$$ = TYPE_CHAR;
|
||||
};
|
||||
|
||||
|
||||
|
||||
simpledecl: fundtype ident T_END {
|
||||
PrimType* t = g_new(PrimType, 1);
|
||||
|
@ -214,7 +247,12 @@ semitype: const_def primtype {
|
|||
$$.indirection++;
|
||||
};
|
||||
|
||||
type: semitype | semitype T_NOTNULLPTR {
|
||||
type: semitype {
|
||||
if(!$$.indirection){
|
||||
g_assert($$.prim->kind != TYPE_OBJECT);
|
||||
g_assert($$.prim->kind != TYPE_BOXED);
|
||||
}
|
||||
} | semitype T_NOTNULLPTR {
|
||||
$$ = $1;
|
||||
$$.indirection++;
|
||||
$$.notnull = TRUE;
|
||||
|
@ -231,14 +269,18 @@ typeorvoid: type | T_VOID {
|
|||
};
|
||||
|
||||
|
||||
primtype: ident T_SCOPE ident {
|
||||
Package* p=get_pkg($1);
|
||||
primtype: maybeident T_SCOPE ident {
|
||||
Id i = $1;
|
||||
Package* p;
|
||||
PrimType* t;
|
||||
if(!i)
|
||||
i = GET_ID("");
|
||||
p = get_pkg(i);
|
||||
if(!p)
|
||||
g_error("Unknown package %s!", $1);
|
||||
g_error("Unknown package %s!", i);
|
||||
t = get_type(p, $3);
|
||||
if(!t)
|
||||
g_error("Unknown type %s:%s", $1, $3);
|
||||
g_error("Unknown type %s:%s", i, $3);
|
||||
$$ = t;
|
||||
} | ident {
|
||||
Package* p = current_module->package;
|
||||
|
@ -358,7 +400,8 @@ flagsdef: T_FLAGS primtype docstring T_OPEN_B idlist T_CLOSE_B T_END {
|
|||
};
|
||||
|
||||
parent: /* empty */{
|
||||
$$=NULL;
|
||||
g_assert(root_class);
|
||||
$$ = root_class;
|
||||
} | T_INHERITANCE primtype{
|
||||
$$=$2;
|
||||
}
|
||||
|
|
|
@ -117,28 +117,22 @@ void p_unref(PNode* node){
|
|||
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);
|
||||
p_write(func(value), c->f, c->p);
|
||||
else
|
||||
p_write(value, c->w);
|
||||
p_write(value, c->f, c->p);
|
||||
}
|
||||
|
||||
|
||||
static void p_write(PNode* node, PWrite* w){
|
||||
void p_write(PNode* node, FILE* f, PRoot* r){
|
||||
g_assert(f);
|
||||
BE_NODE(node);
|
||||
switch(node->type){
|
||||
case NODE_DATA:{
|
||||
|
@ -147,25 +141,40 @@ static void p_write(PNode* node, PWrite* w){
|
|||
|
||||
for(i = 0; i < n; i++){
|
||||
if(bl[i].str)
|
||||
fputs(bl[i].str, w->f);
|
||||
p_write(bl[i].node, w);
|
||||
fputs(bl[i].str, f);
|
||||
p_write(bl[i].node, f, r);
|
||||
}
|
||||
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);
|
||||
case NODE_COLLECT:
|
||||
if(r){
|
||||
GHashTable* h = g_datalist_id_get_data(&r->data,
|
||||
node->u.c.tag);
|
||||
PCollect c;
|
||||
c.f = f;
|
||||
c.p = r;
|
||||
c.n = node;
|
||||
if(h)
|
||||
g_hash_table_foreach(h, cb_pwrite, &c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gchar* p_to_str(PNode* n, PRoot* pr){
|
||||
FILE* f = tmpfile();
|
||||
glong len;
|
||||
gchar* buf;
|
||||
p_write(n, f, pr);
|
||||
len = ftell(f);
|
||||
rewind(f);
|
||||
buf = g_new(gchar, len+1);
|
||||
fread(buf, len, 1, f);
|
||||
buf[len]='\0';
|
||||
fclose(f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static PNode* p_simple_string(gchar* str){
|
||||
|
@ -180,6 +189,9 @@ static PNode* p_simple_string(gchar* str){
|
|||
PNode* p_str(const gchar* str){
|
||||
PNode* n;
|
||||
|
||||
if(!str)
|
||||
return p_nil;
|
||||
|
||||
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);
|
||||
|
@ -270,7 +282,8 @@ PRoot* pr_new(void){
|
|||
return pr;
|
||||
}
|
||||
|
||||
void pr_add(PRoot* pr, const gchar* tag, PNode* node){
|
||||
/*
|
||||
void pr_add(PRoot* pr, const gchar* tag, PNode* node){
|
||||
PRNode* n;
|
||||
g_assert(pr);
|
||||
BE_NODE(node);
|
||||
|
@ -282,7 +295,7 @@ void pr_add(PRoot* pr, const gchar* tag, PNode* node){
|
|||
pr->nodes = g_list_prepend(pr->nodes, n);
|
||||
p_ref(node);
|
||||
}
|
||||
|
||||
*/
|
||||
void pr_put(PRoot* pr, const gchar* tag, gpointer datum){
|
||||
GHashTable* h = g_datalist_get_data(&pr->data, tag);
|
||||
if(!h){
|
||||
|
@ -293,38 +306,6 @@ void pr_put(PRoot* pr, const gchar* tag, gpointer datum){
|
|||
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;
|
||||
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;
|
||||
|
|
|
@ -19,13 +19,15 @@ PNode* p_fmt(const gchar* f, ...);
|
|||
PNode* p_lst(PNode* n, ...);
|
||||
PNode* p_for(GSList* l, PNodeCreateFunc func, gpointer user_data);
|
||||
PNode* p_col(const gchar* tag, PNodeCreateFunc func);
|
||||
void p_write(PNode* node, FILE* f, PRoot* r);
|
||||
gchar* p_to_str(PNode* n, PRoot* pr);
|
||||
|
||||
|
||||
|
||||
PRoot* pr_new(void);
|
||||
void pr_add(PRoot* root, const gchar* tag, PNode* node);
|
||||
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);
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue