mirror of https://github.com/GNOME/gimp.git
Initially committed to CVS.
This commit is contained in:
parent
9005889d05
commit
91f868467c
|
@ -0,0 +1,3 @@
|
|||
1998-10-21 Lauri Alanko <la@iki.fi>
|
||||
|
||||
* Initially committed to CVS
|
|
@ -0,0 +1,38 @@
|
|||
noinst_PROGRAMS = gcg
|
||||
|
||||
|
||||
CFLAGS=-I/usr/local/lib/glib/include -DYYDEBUG=1 -g -Wall -W -DCPP="$(CPP)"
|
||||
INCLUDES = -DYYDEBUG=1 @GLIB_CFLAGS@
|
||||
YFLAGS = -d -v 2>/dev/null
|
||||
LIBS = @GLIB_LIBS@
|
||||
|
||||
lexer.c: $(srcdir)/lexer.l
|
||||
@rm -f $@
|
||||
$(LEX) $(LFLAGS) -t $< >$@
|
||||
|
||||
parser.c parser.h: $(srcdir)/parser.y
|
||||
$(YACC) $(YFLAGS) $<
|
||||
test -f y.tab.c && mv -f y.tab.c parser.c
|
||||
test -f y.tab.h && mv -f y.tab.h parser.h
|
||||
|
||||
MOSTLYCLEANFILES = parser.output y.output
|
||||
DISTCLEANFILES = parser.c parser.h lexer.c
|
||||
EXTRA_DIST = parser.y lexer.l
|
||||
|
||||
BUILT_SOURCES = lexer.c parser.c parser.h
|
||||
|
||||
gcg_SOURCES = \
|
||||
gcg.c \
|
||||
parser.c \
|
||||
lexer.c \
|
||||
output.c \
|
||||
output_basic.c \
|
||||
db.c \
|
||||
output_type.c \
|
||||
output_enum.c \
|
||||
output_flags.c \
|
||||
output_object.c \
|
||||
parser.h
|
||||
|
||||
gcg_DEPENDS = parser.h
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
GCG - docs forthcoming (hopefully)
|
||||
|
||||
GCG is under development, it doesn't do much of anything sensible yet. What
|
||||
little it does, you can test with:
|
||||
|
||||
gcg -t gimpimageT.h -f gimpimage.h -p gimpimageP.h -s gimpimage.c gimpimage.def
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/sh
|
||||
|
||||
if test -z "$*"; then
|
||||
echo "I am going to run ./configure with no arguments - if you wish "
|
||||
echo "to pass any to it, please specify them on the $0 command line."
|
||||
fi
|
||||
|
||||
echo processing...
|
||||
|
||||
aclocal $ACLOCAL_FLAGS &&
|
||||
automake --foreign &&
|
||||
autoconf &&
|
||||
./configure "$@"
|
||||
|
||||
if [ $? -eq 0 ];then
|
||||
echo "Now type 'make' to compile GCG."
|
||||
else
|
||||
echo "Configuration error!"
|
||||
fi
|
|
@ -0,0 +1,8 @@
|
|||
AC_INIT(gcg.c)
|
||||
AM_INIT_AUTOMAKE(gcg, 0.1)
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_YACC
|
||||
AM_PROG_LEX
|
||||
AM_PATH_GLIB(1.0.0,,AC_ERROR(need at least Glib version 1.0))
|
||||
AC_OUTPUT(Makefile)
|
|
@ -0,0 +1,25 @@
|
|||
#include "gcg.h"
|
||||
|
||||
|
||||
void put_decl(PrimType* t){
|
||||
g_hash_table_insert(decl_hash, &t->name, t);
|
||||
}
|
||||
|
||||
void put_def(Def* d){
|
||||
g_hash_table_insert(def_hash, &d->type->name, d);
|
||||
}
|
||||
|
||||
Def* get_def(Id module, Id type){
|
||||
TypeName n;
|
||||
n.module=module;
|
||||
n.type=type;
|
||||
return g_hash_table_lookup(def_hash, &n);
|
||||
}
|
||||
|
||||
PrimType* get_decl(Id module, Id type){
|
||||
TypeName n;
|
||||
n.module=module;
|
||||
n.type=type;
|
||||
return g_hash_table_lookup(decl_hash, &n);
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
#include "gcg.h"
|
||||
#include "parser.h"
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
#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;
|
||||
|
||||
Id func_hdr_name;
|
||||
Id type_hdr_name;
|
||||
Id prot_hdr_name;
|
||||
Id source_name;
|
||||
Id impl_name;
|
||||
|
||||
|
||||
void get_options(int argc, char* argv[]){
|
||||
gint x=0;
|
||||
do{
|
||||
x=getopt(argc, argv, "f:t:p:s:i:");
|
||||
switch(x){
|
||||
case 'f':
|
||||
func_hdr_name=optarg;
|
||||
break;
|
||||
case 't':
|
||||
type_hdr_name=optarg;
|
||||
break;
|
||||
case 'p':
|
||||
prot_hdr_name=optarg;
|
||||
break;
|
||||
case 's':
|
||||
source_name=optarg;
|
||||
break;
|
||||
case 'i':
|
||||
impl_name=optarg;
|
||||
break;
|
||||
case '?':
|
||||
case ':':
|
||||
g_error("Bad option %c!\n", x);
|
||||
}
|
||||
}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_type(TypeName* t, Def* def, gpointer foo){
|
||||
def->klass->output(def);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]){
|
||||
extern int yydebug;
|
||||
extern FILE* yyin;
|
||||
/* target=stdout;*/
|
||||
|
||||
decl_hash=g_hash_table_new(type_name_hash, type_name_cmp);
|
||||
def_hash=g_hash_table_new(type_name_hash, type_name_cmp);
|
||||
yydebug=0;
|
||||
get_options(argc, 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_decl(GET_ID("Gtk"), GET_ID("Type"));
|
||||
g_assert(type_gtk_type->prim);
|
||||
func_hdr=file_new(func_hdr_name);
|
||||
type_hdr=file_new(type_hdr_name);
|
||||
prot_hdr=file_new(prot_hdr_name);
|
||||
source=file_new(source_name);
|
||||
source_head=file_sub(source);
|
||||
g_hash_table_foreach(def_hash, output_type, NULL);
|
||||
file_flush(func_hdr);
|
||||
file_flush(type_hdr);
|
||||
file_flush(source_head);
|
||||
/* file_flush(source);*/
|
||||
file_flush(prot_hdr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
#ifndef __GCG_H__
|
||||
#define __GCG_H__
|
||||
#include <glib.h>
|
||||
|
||||
typedef const gchar* Id;
|
||||
|
||||
#define GET_ID(x) (g_quark_to_string(g_quark_from_string(x)))
|
||||
|
||||
typedef const gchar* Header;
|
||||
|
||||
typedef struct _Member Member;
|
||||
typedef struct _TypeName TypeName;
|
||||
typedef struct _PrimType PrimType;
|
||||
typedef struct _Type Type;
|
||||
typedef struct _ObjectDef ObjectDef;
|
||||
typedef struct _Def Def;
|
||||
typedef struct _EnumDef EnumDef;
|
||||
typedef struct _FlagsDef FlagsDef;
|
||||
typedef struct _DataMember DataMember;
|
||||
typedef struct _Method Method;
|
||||
typedef struct _MemberClass MemberClass;
|
||||
typedef struct _DefClass DefClass;
|
||||
typedef struct _Param Param;
|
||||
|
||||
|
||||
struct _TypeName {
|
||||
Id module;
|
||||
Id type;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
TYPE_CLASS,
|
||||
TYPE_OPAQUE,
|
||||
TYPE_TRANSPARENT
|
||||
} TypeKind;
|
||||
|
||||
|
||||
struct _PrimType {
|
||||
TypeName name;
|
||||
TypeKind kind;
|
||||
Id decl_header;
|
||||
Id def_header;
|
||||
};
|
||||
|
||||
struct _Type {
|
||||
gboolean is_const; /* concerning the _ultimate dereferenced_ object */
|
||||
gint indirection; /* num of pointers to type */
|
||||
gboolean notnull; /* concerning the _immediate pointer_ */
|
||||
PrimType* prim;
|
||||
};
|
||||
|
||||
struct _DefClass {
|
||||
void (*output)(Def*);
|
||||
};
|
||||
|
||||
struct _Def {
|
||||
DefClass *klass;
|
||||
PrimType *type;
|
||||
GString* doc;
|
||||
};
|
||||
|
||||
#define DEF(x) ((Def*)(x))
|
||||
|
||||
extern DefClass enum_class;
|
||||
|
||||
struct _EnumDef {
|
||||
Def def;
|
||||
GSList* alternatives; /* list of Id */
|
||||
};
|
||||
|
||||
extern DefClass flags_class;
|
||||
|
||||
struct _FlagsDef {
|
||||
Def def;
|
||||
GSList* flags; /* list of Id */
|
||||
};
|
||||
|
||||
extern DefClass object_class;
|
||||
|
||||
struct _ObjectDef {
|
||||
Def def;
|
||||
PrimType* parent;
|
||||
GSList* members;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
KIND_DIRECT,
|
||||
KIND_ABSTRACT,
|
||||
KIND_STATIC
|
||||
} MemberKind;
|
||||
|
||||
typedef enum {
|
||||
METH_PUBLIC,
|
||||
METH_PROTECTED
|
||||
} MethodProtection;
|
||||
|
||||
typedef enum {
|
||||
DATA_READWRITE,
|
||||
DATA_READONLY,
|
||||
DATA_PROTECTED
|
||||
} DataProtection;
|
||||
|
||||
typedef enum _EmitDef{
|
||||
EMIT_NONE,
|
||||
EMIT_PRE,
|
||||
EMIT_POST
|
||||
} EmitDef;
|
||||
|
||||
typedef enum _MemberType{
|
||||
MEMBER_DATA,
|
||||
MEMBER_METHOD,
|
||||
MEMBER_SIGNAL
|
||||
} MemberType;
|
||||
|
||||
|
||||
struct _Member{
|
||||
MemberType membertype;
|
||||
MemberKind kind;
|
||||
ObjectDef* my_class;
|
||||
Id name;
|
||||
GString* doc;
|
||||
};
|
||||
|
||||
#define MEMBER(x) ((Member*)(x))
|
||||
|
||||
struct _DataMember {
|
||||
Member member;
|
||||
DataProtection prot;
|
||||
Type type;
|
||||
};
|
||||
|
||||
struct _Method {
|
||||
Member member;
|
||||
MethodProtection prot;
|
||||
GSList* params; /* list of Param* */
|
||||
gboolean self_const;
|
||||
Type ret_type;
|
||||
};
|
||||
|
||||
|
||||
struct _Param {
|
||||
Id name;
|
||||
Method* method;
|
||||
GString* doc;
|
||||
Type type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void put_decl(PrimType* t);
|
||||
void put_def(Def* d);
|
||||
PrimType* get_decl(Id module, Id type);
|
||||
Def* get_def(Id module, Id type);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
module g {
|
||||
header <glib.h> {
|
||||
type int;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
module Gtk {
|
||||
header <gtk/gtktypeutils.h> {
|
||||
type Type;
|
||||
};
|
||||
};
|
||||
|
||||
module Gimp{
|
||||
header <gimp/gimpobject.h> {
|
||||
class Object;
|
||||
};
|
||||
header <gimp/gimpimage.h> {
|
||||
class Image;
|
||||
type ImageType;
|
||||
type Thingy;
|
||||
};
|
||||
enum ImageType{
|
||||
rgb, gray, indexed, rgb-alpha };
|
||||
flags Thingy{
|
||||
foo, bar, baz, quux
|
||||
};
|
||||
class Image : Gimp.Object{
|
||||
g.int x;
|
||||
read-only g.int y;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,73 @@
|
|||
%option noyywrap
|
||||
|
||||
%{
|
||||
#include "gcg.h"
|
||||
#include "parser.h"
|
||||
%}
|
||||
|
||||
ident [A-Za-z][A-Za-z0-9-]*
|
||||
header <[[:alnum:]/.]+>
|
||||
ws [ \n\t\r]
|
||||
comment \/\/[^\n]*\n
|
||||
string \"(([^\"]*)|\\\"|\\\\)*\"
|
||||
|
||||
%%
|
||||
|
||||
class return T_CLASS;
|
||||
public return T_PUBLIC;
|
||||
static return T_STATIC;
|
||||
protected return T_PROTECTED;
|
||||
pre-emit return T_PRE_EMIT;
|
||||
post-emit return T_POST_EMIT;
|
||||
read-only return T_READ_ONLY;
|
||||
read-write return T_READ_WRITE;
|
||||
private return T_PRIVATE;
|
||||
const return T_CONST;
|
||||
abstract return T_ABSTRACT;
|
||||
direct return T_DIRECT;
|
||||
type return T_TYPE;
|
||||
attribute return T_ATTRIBUTE;
|
||||
module return T_MODULE;
|
||||
enum return T_ENUM;
|
||||
flags return T_FLAGS;
|
||||
import return T_IMPORT;
|
||||
header return T_HEADER;
|
||||
opaque return T_OPAQUE;
|
||||
void return T_VOID;
|
||||
|
||||
{comment} {
|
||||
}
|
||||
|
||||
{ws} {
|
||||
}
|
||||
|
||||
{ident} {
|
||||
yylval.id=g_quark_to_string(g_quark_from_string(yytext));
|
||||
return T_IDENT;
|
||||
}
|
||||
|
||||
{header} {
|
||||
yylval.id=g_quark_to_string(g_quark_from_string(yytext));
|
||||
return T_HEADERNAME;
|
||||
}
|
||||
|
||||
|
||||
{string} {
|
||||
yylval.str=g_string_new(yytext);
|
||||
return T_STRING;
|
||||
}
|
||||
|
||||
\. return T_SCOPE;
|
||||
\* return T_POINTER;
|
||||
\& return T_NOTNULLPTR;
|
||||
\; return T_END;
|
||||
\{ return T_OPEN_B;
|
||||
\} return T_CLOSE_B;
|
||||
\( return T_OPEN_P;
|
||||
\) return T_CLOSE_P;
|
||||
\, return T_COMMA;
|
||||
\: return T_INHERITANCE;
|
||||
. return yytext[0];
|
||||
|
||||
%%
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#include "classc.h"
|
||||
#include "parser.h"
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
#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;
|
||||
|
||||
|
||||
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_type(TypeName* t, Def* def, gpointer foo){
|
||||
def->klass->output(def);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]){
|
||||
extern int yydebug;
|
||||
extern FILE* yyin;
|
||||
/* target=stdout;*/
|
||||
|
||||
decl_hash=g_hash_table_new(type_name_hash, type_name_cmp);
|
||||
def_hash=g_hash_table_new(type_name_hash, type_name_cmp);
|
||||
yydebug=0;
|
||||
yyin=fopen(argv[1], "r");
|
||||
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_decl(GET_ID("Gtk"), GET_ID("Type"));
|
||||
g_assert(type_gtk_type->prim);
|
||||
func_hdr=file_new("gen_funcs.h");
|
||||
type_hdr=file_new("gen_types.h");
|
||||
prot_hdr=file_new("gen_prots.h");
|
||||
source=file_new("gen_source.c");
|
||||
source_head=file_sub(source);
|
||||
g_hash_table_foreach(def_hash, output_type, NULL);
|
||||
file_flush(func_hdr);
|
||||
file_flush(type_hdr);
|
||||
file_flush(source_head);
|
||||
/* file_flush(source);*/
|
||||
file_flush(prot_hdr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
#include <stdio.h>
|
||||
#include "output.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
void pr_param(File* s, Param* p, PBool first){
|
||||
pr(s, "%?s%1 %s",
|
||||
!first, ", ",
|
||||
pr_type, p->type,
|
||||
p->name);
|
||||
}
|
||||
|
||||
void pr_params(File* s, GSList* args){
|
||||
pr(s, "%?s%?2%3",
|
||||
!args, "void",
|
||||
!!args, pr_param, args?args->data:NULL, ptrue,
|
||||
pr_list_foreach, (args?args->next:NULL), pr_param, pfalse);
|
||||
}
|
||||
|
||||
void pr_primtype(File* s, PrimType* t){
|
||||
pr(s, "%s%s",
|
||||
t->name.module,
|
||||
t->name.type);
|
||||
}
|
||||
|
||||
void pr_type(File* s, Type* t){
|
||||
gint i=t->indirection;
|
||||
if(t->prim){
|
||||
pr(s, "%?s%1",
|
||||
t->is_const, "const ",
|
||||
pr_primtype, t->prim);
|
||||
while(i--)
|
||||
pr_c(s, '*');
|
||||
if(t->indirection)
|
||||
file_add_dep(s, t->prim->decl_header);
|
||||
else
|
||||
file_add_dep(s, t->prim->def_header);
|
||||
}else
|
||||
pr(s, "void");
|
||||
}
|
||||
|
||||
void pr_self_type(File* s, ObjectDef* o, PBool const_self){
|
||||
pr(s, "%?s%2*",
|
||||
!!const_self, "const ",
|
||||
pr_primtype, DEF(o)->type);
|
||||
}
|
||||
|
||||
void pr_varname(File* s, PrimType* t, Id name){
|
||||
pr(s, "%1_%1_%1",
|
||||
pr_low, t->name.module,
|
||||
pr_low, t->name.type,
|
||||
pr_low, name);
|
||||
}
|
||||
|
||||
void pr_internal_varname(File* s, PrimType* t, Id name){
|
||||
pr(s, "_%2",
|
||||
pr_varname, t, name);
|
||||
}
|
||||
|
||||
|
||||
void pr_prototype(File* s, PrimType* type, Id funcname,
|
||||
GSList* params, Type* rettype, gboolean internal){
|
||||
pr(s, "%1 %2 (%1)",
|
||||
pr_type, rettype,
|
||||
(internal?pr_internal_varname:pr_varname), type, funcname,
|
||||
pr_params, params);
|
||||
}
|
||||
|
||||
void pr_type_guard(File* s, Param* p){
|
||||
Type* t=&p->type;
|
||||
if(t->indirection==1 && t->prim->kind == TYPE_CLASS)
|
||||
/* A direct object pointer is checked for its type */
|
||||
pr(s, "\tg_assert(%?2%3(%s));",
|
||||
!t->notnull, pr, "!%s || ", p->name,
|
||||
pr_macro_name, t->prim->name, "IS", NULL,
|
||||
p->name);
|
||||
else if(t->indirection && t->notnull)
|
||||
/* Other pointers are just possibly checked for nullness */
|
||||
pr(s, "\tg_assert(%s);",
|
||||
p->name);
|
||||
/* todo (low priority): range checks for enums */
|
||||
}
|
||||
|
||||
|
||||
void output_func(PrimType* type, Id funcname, GSList* params, Type* rettype,
|
||||
File* hdr, ObjectDef* self, gboolean self_const,
|
||||
gboolean internal, const gchar* body, ...){
|
||||
GSList l;
|
||||
Param p;
|
||||
va_list args;
|
||||
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;
|
||||
}
|
||||
va_start(args, body);
|
||||
pr((hdr?hdr:source_head), "%?s%5;\n",
|
||||
!hdr, "static ",
|
||||
pr_prototype, type, funcname, params, rettype, internal);
|
||||
pr(source,
|
||||
"%?s%5{\n"
|
||||
"%3"
|
||||
"%v"
|
||||
"}\n",
|
||||
!hdr, "static ",
|
||||
pr_prototype, type, funcname, params, rettype, internal,
|
||||
pr_list_foreach, params, pr_type_guard, no_data,
|
||||
body, args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pr_macro_name(File* s, PrimType* t, Id mid, Id post){
|
||||
pr(s,
|
||||
"%1%?s%?1_%1%?s%?1",
|
||||
pr_up, t->name.module,
|
||||
!!mid, "_",
|
||||
!!mid, pr_up, mid,
|
||||
pr_up, t->name.type,
|
||||
!!post, "_",
|
||||
!!post, pr_up, post);
|
||||
}
|
||||
|
||||
void output_var(Def* d, Type* t, Id varname, File* hdr, gboolean internal){
|
||||
if(hdr)
|
||||
pr(hdr,
|
||||
"extern %1 %2;\n",
|
||||
pr_type, t,
|
||||
(internal?pr_internal_varname:pr_varname), &d->type->name,
|
||||
varname);
|
||||
pr(source_head,
|
||||
"%?s%1 %2;\n",
|
||||
!hdr, "static ",
|
||||
pr_type, t,
|
||||
(internal?pr_internal_varname:pr_varname), &d->type->name,
|
||||
varname);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#ifndef __OUTPUT_H__
|
||||
#define __OUTPUT_H__
|
||||
|
||||
#include "gcg.h"
|
||||
#include <stdio.h>
|
||||
typedef gconstpointer PBool;
|
||||
extern const PBool ptrue;
|
||||
extern const PBool pfalse;
|
||||
|
||||
typedef enum{
|
||||
VAR_STATIC,
|
||||
VAR_PUBLIC,
|
||||
VAR_PROTECTED
|
||||
} VarProt;
|
||||
|
||||
typedef struct _File File;
|
||||
File* file_new(const gchar* filename);
|
||||
void file_flush(File* f);
|
||||
void file_add_dep(File* f, Id header);
|
||||
|
||||
extern File* type_hdr;
|
||||
extern File* func_hdr;
|
||||
extern File* prot_hdr;
|
||||
extern File* pub_import_hdr;
|
||||
extern File* prot_import_hdr;
|
||||
extern File* source;
|
||||
extern File* source_head; /* "private header", so to say */
|
||||
|
||||
void pr(File* s, const gchar* f, ...);
|
||||
void prv(File* s, const gchar* f, va_list args);
|
||||
void pr_nil(File* s, ...);
|
||||
void pr_c(File* s, gchar c);
|
||||
void pr_low(File* s, const gchar* str);
|
||||
void pr_up(File* s, const gchar* str);
|
||||
|
||||
extern const gconstpointer no_data;
|
||||
|
||||
void pr_list_foreach(File* s, GSList* l, void (*f)(), gpointer arg);
|
||||
void pr_params(File* s, GSList* args);
|
||||
void pr_primtype(File* s, PrimType* t);
|
||||
void pr_type(File* s, Type* t);
|
||||
void pr_self_type(File* s, ObjectDef* c, PBool const_self);
|
||||
void pr_varname(File* s, PrimType* t, Id name);
|
||||
void pr_internal_varname(File* s, PrimType* t, Id name);
|
||||
void pr_object_member(File* s, Member* m);
|
||||
void pr_object_body(File* s, ObjectDef* c);
|
||||
void pr_object_decl(File* s, ObjectDef* c);
|
||||
void pr_class_member(File* s, Member* m);
|
||||
void pr_class_body(File* s, ObjectDef* c);
|
||||
void pr_class_decl(File* s, ObjectDef* c);
|
||||
void pr_prototype(File* s, PrimType* type, Id funcname,
|
||||
GSList* params, Type* rettype, gboolean internal);
|
||||
|
||||
void pr_func(ObjectDef* self, Id funcname, GSList* params, Type* rettype,
|
||||
VarProt prot, gboolean with_self, const gchar* body, ...);
|
||||
|
||||
void pr_macro_name(File* s, PrimType* t, Id mid, Id post);
|
||||
void pr_class_macros(File* s, ObjectDef* c );
|
||||
void pr_get_type(File* s, ObjectDef* c);
|
||||
void pr_gtype(File* s, Type* t);
|
||||
void pr_guard_name(File* s, const gchar* c);
|
||||
void pr_guard_start(File* s, const gchar *c);
|
||||
void pr_guard_end(File* s, const gchar *c);
|
||||
#endif
|
|
@ -0,0 +1,256 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <glib.h>
|
||||
#include <ctype.h>
|
||||
#include "output.h"
|
||||
|
||||
const PBool ptrue = &ptrue;
|
||||
const PBool pfalse = NULL;
|
||||
File* type_hdr;
|
||||
File* func_hdr;
|
||||
File* prot_hdr;
|
||||
File* pub_import_hdr;
|
||||
File* prot_import_hdr;
|
||||
File* source;
|
||||
File* source_head; /* inlined to the source */
|
||||
|
||||
struct _File{
|
||||
FILE* stream;
|
||||
const gchar* filename;
|
||||
File* parent;
|
||||
GHashTable* deps;
|
||||
};
|
||||
|
||||
void write_guard_name(FILE* s, const gchar* c){
|
||||
gboolean enc=FALSE;
|
||||
fputs("_g_", s);
|
||||
while(*c){
|
||||
if(isalnum(*c))
|
||||
fputc(*c, s);
|
||||
else
|
||||
fputc('_', s);
|
||||
c++;
|
||||
}
|
||||
fputc('_', s);
|
||||
}
|
||||
|
||||
void write_guard_start(FILE* s, const gchar *c){
|
||||
fputs("#ifndef ", s);
|
||||
write_guard_name(s, c);
|
||||
fputs("\n#define ", s);
|
||||
write_guard_name(s, c);
|
||||
fputs("\n", s);
|
||||
}
|
||||
|
||||
void write_guard_end(FILE* s, const gchar *c){
|
||||
fputs("#endif /* ", s);
|
||||
write_guard_name(s, c);
|
||||
fputs(" */\n", s);
|
||||
}
|
||||
|
||||
|
||||
File* file_new(const gchar* filename){
|
||||
File* f=g_new(File, 1);
|
||||
f->stream=tmpfile();
|
||||
f->filename=filename;
|
||||
f->deps=g_hash_table_new(g_str_hash, g_str_equal);
|
||||
f->parent=NULL;
|
||||
return f;
|
||||
}
|
||||
|
||||
File* file_sub(File* parent){
|
||||
File* f=g_new(File, 1);
|
||||
f->stream=tmpfile();
|
||||
f->filename=NULL;
|
||||
f->deps=NULL;
|
||||
f->parent=parent;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
void file_add_dep(File* f, Id header){
|
||||
while(f->parent)
|
||||
f=f->parent;
|
||||
g_hash_table_insert(f->deps, header, NULL);
|
||||
}
|
||||
|
||||
void write_dep(gpointer key, gpointer value, gpointer user_data){
|
||||
Id i=key;
|
||||
FILE* stream=user_data;
|
||||
fprintf(stream, "#include %s\n", i);
|
||||
}
|
||||
|
||||
void file_flush(File* f){
|
||||
File* root;
|
||||
File* old;
|
||||
static const gint bufsize=1024;
|
||||
FILE* real;
|
||||
guint8 buf[bufsize];
|
||||
size_t i;
|
||||
for(root=f;root->parent;root=root->parent);
|
||||
real=fopen(root->filename, "w+");
|
||||
g_assert(real);
|
||||
write_guard_start(real, root->filename); /* more scoping needed */
|
||||
g_hash_table_foreach(root->deps, write_dep, real);
|
||||
fflush(root->stream);
|
||||
old=NULL;
|
||||
while(f){
|
||||
g_free(old);
|
||||
rewind(f->stream);
|
||||
i=0;
|
||||
do{
|
||||
i=fread(buf, 1, bufsize, f->stream);
|
||||
fwrite(buf, 1, i, real);
|
||||
}while(i==bufsize);
|
||||
fclose(f->stream);
|
||||
old=f;
|
||||
f=f->parent;
|
||||
}
|
||||
write_guard_end(real, root->filename);
|
||||
fclose(real);
|
||||
g_hash_table_destroy(root->deps);
|
||||
g_free(root);
|
||||
}
|
||||
|
||||
typedef void (*Func)();
|
||||
|
||||
const Func nilf = 0;
|
||||
|
||||
static void call_func(Func fun, File* s, gpointer* x, gint nargs){
|
||||
switch(nargs){
|
||||
case 0:
|
||||
fun(s);
|
||||
break;
|
||||
case 1:
|
||||
fun(s, x[0]);
|
||||
break;
|
||||
case 2:
|
||||
fun(s, x[0], x[1]);
|
||||
break;
|
||||
case 3:
|
||||
fun(s, x[0], x[1], x[2]);
|
||||
break;
|
||||
case 4:
|
||||
fun(s, x[0], x[1], x[2], x[3]);
|
||||
break;
|
||||
case 5:
|
||||
fun(s, x[0], x[1], x[2], x[3], x[4]);
|
||||
break;
|
||||
case 6:
|
||||
fun(s, x[0], x[1], x[2], x[3], x[4], x[5]);
|
||||
break;
|
||||
case 7:
|
||||
fun(s, x[0], x[1], x[2], x[3], x[4], x[5], x[6]);
|
||||
break;
|
||||
case 8:
|
||||
fun(s, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
|
||||
break;
|
||||
case 9:
|
||||
fun(s, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void prv(File* s, const gchar* f, va_list args){
|
||||
gint i=0;
|
||||
if(!s)
|
||||
return;
|
||||
while(*f){
|
||||
while(f[i] && f[i]!='%')
|
||||
i++;
|
||||
fwrite(f, i, 1, s->stream);
|
||||
f+=i;
|
||||
i=0;
|
||||
if(f[0]=='%'){
|
||||
char c=f[1];
|
||||
gboolean doit=TRUE;
|
||||
f+=2;
|
||||
if(c=='%')
|
||||
fputc('%', s->stream);
|
||||
else if(c=='?'){
|
||||
doit=va_arg(args, gboolean);
|
||||
c=*f++;
|
||||
}
|
||||
if(c=='s'){
|
||||
const gchar* str=va_arg(args, const gchar*);
|
||||
if(doit)
|
||||
fputs(str, s->stream);
|
||||
} else if(c=='d'){
|
||||
gint n;
|
||||
n=va_arg(args, gint);
|
||||
fprintf(s->stream, "%d", n);
|
||||
} else if(c=='v'){
|
||||
const gchar* nextformat;
|
||||
va_list nextargs;
|
||||
nextformat=va_arg(args, const gchar*);
|
||||
nextargs=va_arg(args, va_list);
|
||||
if(doit)
|
||||
prv(s, nextformat, nextargs);
|
||||
}else if(c>='0' && c<='9'){
|
||||
Func fun;
|
||||
gint n;
|
||||
gpointer x[8];
|
||||
fun=va_arg(args, Func);
|
||||
for(n=0;n<c-'0';n++)
|
||||
x[n]=va_arg(args, gpointer);
|
||||
if(doit)
|
||||
call_func(fun, s, x, c-'0');
|
||||
} else g_error("Bad format\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void pr(File* s, const gchar* format, ...){
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
prv(s, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void pr_f(File* s, const gchar* format, ...){
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(s->stream, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void pr_nil(File* s, ...){
|
||||
}
|
||||
|
||||
void pr_c(File* s, gchar c){
|
||||
if(s)
|
||||
fputc(c, s->stream);
|
||||
}
|
||||
|
||||
void pr_low(File* s, const gchar* str){
|
||||
gchar x;
|
||||
while(*str){
|
||||
x=*str++;
|
||||
pr_c(s, (x=='-')?'_':tolower(x));
|
||||
}
|
||||
}
|
||||
|
||||
void pr_up(File* s, const gchar* str){
|
||||
gchar x;
|
||||
while(*str){
|
||||
x=*str++;
|
||||
pr_c(s, (x=='-')?'_':toupper(x));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const gconstpointer no_data = &no_data;
|
||||
|
||||
/* This depends on a func pointer being about the same as a gpointer */
|
||||
|
||||
void pr_list_foreach(File* s, GSList* l, void (*f)(), gpointer arg){
|
||||
while(l){
|
||||
if(arg==no_data)
|
||||
f(s, l->data);
|
||||
else
|
||||
f(s, l->data, arg);
|
||||
l=l->next;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#include "output.h"
|
||||
|
||||
void pr_enum_member(File* s, Id id, PrimType* t){
|
||||
pr(s,
|
||||
"\t%3,\n",
|
||||
pr_macro_name, t, NULL, id);
|
||||
}
|
||||
|
||||
void pr_enum_decl(File* s, EnumDef* e){
|
||||
pr(s,
|
||||
"typedef enum {\n"
|
||||
"%3"
|
||||
"} %1;\n",
|
||||
pr_list_foreach, e->alternatives, pr_enum_member, DEF(e)->type,
|
||||
pr_primtype, DEF(e)->type);
|
||||
}
|
||||
|
||||
void pr_enum_value(File* s, Id i, PrimType* t){
|
||||
pr(s,
|
||||
"\t\t{%3,\n"
|
||||
"\t\t\"%3\",\n"
|
||||
"\t\t\"%s\"},\n",
|
||||
pr_macro_name, t, NULL, i,
|
||||
pr_macro_name, t, NULL, i,
|
||||
i);
|
||||
}
|
||||
|
||||
void output_enum_type_init(EnumDef* e){
|
||||
PrimType* t=DEF(e)->type;
|
||||
output_func(t, "init_type", NULL, type_gtk_type, type_hdr, NULL,
|
||||
FALSE, TRUE,
|
||||
"\tstatic GtkEnumValue values[%d] = {\n"
|
||||
"%3"
|
||||
"\t\t{0, NULL, NULL}\n"
|
||||
"\t};\n"
|
||||
"\t%2 = gtk_type_register_enum (\"%1\", values);\n"
|
||||
"\treturn %2;\n",
|
||||
g_slist_length(e->alternatives)+1,
|
||||
pr_list_foreach, e->alternatives, pr_enum_value, t,
|
||||
pr_internal_varname, t, "type",
|
||||
pr_primtype, t,
|
||||
pr_internal_varname, t, "type");
|
||||
}
|
||||
|
||||
void output_enum(EnumDef* e){
|
||||
output_def(DEF(e));
|
||||
output_enum_type_init(e);
|
||||
pr_enum_decl(type_hdr, e);
|
||||
}
|
||||
|
||||
DefClass enum_class={
|
||||
output_enum
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
#include "output.h"
|
||||
|
||||
typedef struct {
|
||||
gint i;
|
||||
PrimType* t;
|
||||
}FlagData;
|
||||
|
||||
void pr_flags_member(File* s, Id id, FlagData* d){
|
||||
pr(s,
|
||||
"\t%3 = 1 << %d,\n",
|
||||
pr_macro_name, d->t, NULL, id,
|
||||
d->i);
|
||||
d->i++;
|
||||
}
|
||||
|
||||
void pr_flags_decl(File* s, FlagsDef* e){
|
||||
FlagData d={
|
||||
0,
|
||||
DEF(e)->type
|
||||
};
|
||||
pr(s,
|
||||
"typedef enum {\n"
|
||||
"%3"
|
||||
"} %1;\n",
|
||||
pr_list_foreach, e->flags, pr_flags_member, &d,
|
||||
pr_primtype, d.t);
|
||||
}
|
||||
|
||||
void pr_flags_value(File* s, Id i, PrimType* t){
|
||||
pr(s,
|
||||
"\t\t{%3,\n"
|
||||
"\t\t\"%3\",\n"
|
||||
"\t\t\"%s\"},\n",
|
||||
pr_macro_name, t, NULL, i,
|
||||
pr_macro_name, t, NULL, i,
|
||||
i);
|
||||
}
|
||||
|
||||
void output_flags_type_init(FlagsDef* e){
|
||||
PrimType* t=DEF(e)->type;
|
||||
output_func(t, "init_type", NULL, type_gtk_type, type_hdr, NULL,
|
||||
FALSE, TRUE,
|
||||
"\tstatic GtkFlagValue values[%d] = {\n"
|
||||
"%3"
|
||||
"\t\t{0, NULL, NULL}\n"
|
||||
"\t};\n"
|
||||
"\t%2 = gtk_type_register_flags (\"%1\", values);\n"
|
||||
"\treturn %2;\n",
|
||||
g_slist_length(e->flags)+1,
|
||||
pr_list_foreach, e->flags, pr_flags_value, t,
|
||||
pr_internal_varname, t, "type",
|
||||
pr_primtype, t,
|
||||
pr_internal_varname, t, "type");
|
||||
}
|
||||
|
||||
void output_flags(FlagsDef* e){
|
||||
output_def(DEF(e));
|
||||
pr_flags_decl(type_hdr, e);
|
||||
output_flags_type_init(e);
|
||||
}
|
||||
|
||||
DefClass flags_class={
|
||||
output_flags
|
||||
};
|
||||
|
||||
Type* type_gtk_type;
|
|
@ -0,0 +1,190 @@
|
|||
#include "output.h"
|
||||
|
||||
void pr_object_member(File* s, Member* m){
|
||||
DataMember* d;
|
||||
if(m->membertype != MEMBER_DATA
|
||||
|| m->kind != KIND_DIRECT)
|
||||
return;
|
||||
d=(DataMember*)m;
|
||||
pr(s, "\t%1 %1;\n",
|
||||
pr_type, &d->type,
|
||||
pr_low, m->name);
|
||||
}
|
||||
|
||||
void pr_object_body(File* s, ObjectDef* o){
|
||||
GSList* l;
|
||||
pr(s, "struct _%1 {\n"
|
||||
"\t%1 parent;\n"
|
||||
"%3"
|
||||
"};\n",
|
||||
pr_primtype, DEF(o)->type,
|
||||
pr_primtype, o->parent,
|
||||
pr_list_foreach, o->members, pr_object_member, no_data);
|
||||
}
|
||||
|
||||
void pr_object_decl(File* s, ObjectDef* o){
|
||||
PrimType* n=DEF(o)->type;
|
||||
pr(s,
|
||||
"#ifdef STRICT_OBJECT_TYPES\n"
|
||||
"typedef struct _%1 %1;\n"
|
||||
"#else\n"
|
||||
"typedef struct _GenericObject %1;\n"
|
||||
"#endif\n",
|
||||
pr_primtype, n,
|
||||
pr_primtype, n,
|
||||
pr_primtype, n);
|
||||
}
|
||||
|
||||
void pr_class_member(File* s, Member* m){
|
||||
#if 0
|
||||
if(m->kind!=KIND_ABSTRACT)
|
||||
return;
|
||||
pr(s, "\t%1 %1%5;\n",
|
||||
pr_type, m->type,
|
||||
(m->method?pr_nil:pr), m->name
|
||||
(m->method?pr:pr_nil), "(*%s) (%2)",
|
||||
m->name,
|
||||
pr_params, m->params, ptrue);
|
||||
#endif
|
||||
}
|
||||
|
||||
void pr_class_name(File* s, PrimType* o){
|
||||
pr(s, "%1Class",
|
||||
pr_primtype, o);
|
||||
}
|
||||
|
||||
void pr_impl_name(File* s, ObjectDef* o){
|
||||
pr(s, "%1Impl",
|
||||
pr_type, DEF(o)->type);
|
||||
}
|
||||
|
||||
|
||||
void pr_class_body(File* s, ObjectDef* o){
|
||||
pr(s,
|
||||
"struct _%1 {\n"
|
||||
"\t%1 parent_class;\n"
|
||||
"%3"
|
||||
"};\n",
|
||||
pr_class_name, DEF(o)->type,
|
||||
pr_class_name, o->parent,
|
||||
pr_list_foreach, o->members, pr_class_member, no_data);
|
||||
}
|
||||
|
||||
void pr_class_decl(File* s, ObjectDef* o){
|
||||
pr(s,
|
||||
"typedef struct _%1 %1;\n",
|
||||
pr_class_name, DEF(o)->type,
|
||||
pr_class_name, DEF(o)->type);
|
||||
}
|
||||
|
||||
void pr_class_cast(File* s, ObjectDef* t, const gchar* format, ...){
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
pr(s, "%3 (%2)",
|
||||
pr_macro_name, DEF(t)->type, NULL, "CLASS_CAST",
|
||||
prv, format, args);
|
||||
}
|
||||
|
||||
|
||||
void pr_abstract_member(File* s, Id varname, ObjectDef* klass, Id membername){
|
||||
pr(s,
|
||||
"(%3->%s)",
|
||||
pr_class_cast, klass, "GTK_OBJECT(%s)->klass", varname,
|
||||
membername);
|
||||
}
|
||||
|
||||
void output_method_funcs(Method* m){
|
||||
PrimType* t=DEF(MEMBER(m)->my_class)->type;
|
||||
Id name=MEMBER(m)->name;
|
||||
output_func
|
||||
(t,
|
||||
name,
|
||||
m->params,
|
||||
&m->ret_type,
|
||||
m->prot==METH_PUBLIC?func_hdr:prot_hdr,
|
||||
MEMBER(m)->my_class,
|
||||
m->self_const,
|
||||
FALSE,
|
||||
"\t%?s%?5%%%%",
|
||||
!!m->ret_type.prim, "return ",
|
||||
MEMBER(m)->kind==KIND_ABSTRACT,
|
||||
pr, "%2%2", pr_abstract_member, "self", t, name
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void pr_accessor_def(...){
|
||||
Param p;
|
||||
GSList l;
|
||||
l.data=&p;
|
||||
mk_self_param(
|
||||
pr_func(m->klass, m->name, ,
|
||||
"\treturn self->%s;\n");
|
||||
*/
|
||||
|
||||
|
||||
void pr_class_macros(File* s, ObjectDef* o ){
|
||||
PrimType* t=DEF(o)->type;
|
||||
pr(s, "#define %3(o) GTK_CHECK_CAST(o, %3, %1)\n",
|
||||
pr_macro_name, t, NULL, NULL,
|
||||
pr_macro_name, t, "TYPE", NULL,
|
||||
pr_primtype, t);
|
||||
pr(s, "#define %3(o) GTK_CHECK_TYPE(o, %3)\n",
|
||||
pr_macro_name, t, "IS", NULL,
|
||||
pr_macro_name, t, "TYPE", NULL);
|
||||
}
|
||||
|
||||
void output_object_type_init(ObjectDef* o){
|
||||
PrimType* t=DEF(o)->type;
|
||||
output_func(t, "init_type", NULL, type_gtk_type, type_hdr, NULL,
|
||||
FALSE, TRUE,
|
||||
"\tstatic GtkTypeInfo info = {\n"
|
||||
"\t\t\"%1\",\n"
|
||||
"\t\tsizeof (%1),\n"
|
||||
"\t\tsizeof (%1),\n"
|
||||
"\t\t(GtkClassInitFunc) %2,\n"
|
||||
"\t\t(GtkObjectInitFunc) %2,\n"
|
||||
"\t\tNULL,\n"
|
||||
"\t\tNULL,\n"
|
||||
"\t\tNULL,\n"
|
||||
"\t};\n"
|
||||
"\t%2 = gtk_type_unique (%3, &info);\n"
|
||||
"\treturn %2;\n",
|
||||
pr_primtype, t,
|
||||
pr_primtype, t,
|
||||
pr_class_name, o,
|
||||
pr_varname, t, "class_init",
|
||||
pr_varname, t, "init",
|
||||
pr_internal_varname, t, "type",
|
||||
pr_macro_name, o->parent, "TYPE", NULL,
|
||||
pr_internal_varname, t, "type");
|
||||
}
|
||||
|
||||
void pr_gtype(File* s, Type* t){
|
||||
if((t->indirection==0 && t->prim->kind==TYPE_TRANSPARENT)
|
||||
|| (t->indirection==1 && t->prim->kind==TYPE_CLASS))
|
||||
pr_macro_name(s, t->prim, "TYPE", NULL);
|
||||
else if(t->indirection)
|
||||
pr(s, "GTK_TYPE_POINTER");
|
||||
else
|
||||
g_error("Illegal non-pointer type %s%s\n",
|
||||
t->prim->name.module,
|
||||
t->prim->name.type);
|
||||
}
|
||||
|
||||
void output_object(ObjectDef* o){
|
||||
output_def(DEF(o));
|
||||
output_object_type_init(o);
|
||||
pr_class_body(prot_hdr, o);
|
||||
pr_class_decl(prot_hdr, o);
|
||||
pr_object_decl(type_hdr, o);
|
||||
pr_object_body(prot_hdr, o);
|
||||
}
|
||||
|
||||
|
||||
|
||||
DefClass object_class={
|
||||
output_object
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#include "output.h"
|
||||
|
||||
void output_def(Def* d){
|
||||
TypeName* t=&d->type->name;
|
||||
/* GTK_TYPE_FOO macro */
|
||||
pr(type_hdr,
|
||||
"#define %3 \\\n"
|
||||
" (%2 ? %2 : %2())\n",
|
||||
pr_macro_name, t, "TYPE", NULL,
|
||||
pr_internal_varname, t, "type",
|
||||
pr_internal_varname, t, "type",
|
||||
pr_internal_varname, t, "init_type");
|
||||
output_var(d, type_gtk_type, "type", type_hdr, TRUE);
|
||||
}
|
|
@ -0,0 +1,362 @@
|
|||
%{
|
||||
#include "gcg.h"
|
||||
#define YYDEBUG 1
|
||||
%}
|
||||
|
||||
%union {
|
||||
GSList* list;
|
||||
Id id;
|
||||
GString* str;
|
||||
TypeName typename;
|
||||
PrimType* primtype;
|
||||
MethodProtection methprot;
|
||||
DataProtection dataprot;
|
||||
MemberKind kind;
|
||||
Def* def;
|
||||
ObjectDef* class_def;
|
||||
Member* member;
|
||||
Param* param;
|
||||
EmitDef emit_def;
|
||||
gboolean bool;
|
||||
Type type;
|
||||
};
|
||||
|
||||
%token T_MODULE
|
||||
%token T_ENUM
|
||||
%token T_FLAGS
|
||||
%token T_READ_WRITE
|
||||
%token T_READ_ONLY
|
||||
%token T_PRIVATE
|
||||
%token T_PROTECTED
|
||||
%token T_PUBLIC
|
||||
%token T_CLASS
|
||||
%token T_PRE_EMIT
|
||||
%token T_POST_EMIT
|
||||
%token T_SCOPE
|
||||
%token T_ABSTRACT
|
||||
%token T_EMPTY
|
||||
%token T_DIRECT
|
||||
%token T_STATIC
|
||||
%token T_CONST
|
||||
%token T_TYPE
|
||||
%token T_END
|
||||
%token T_OPEN_B
|
||||
%token T_POINTER
|
||||
%token T_NOTNULLPTR
|
||||
%token T_CLOSE_B
|
||||
%token T_INHERITANCE
|
||||
%token T_ATTRIBUTE
|
||||
%token T_HEADER
|
||||
%token T_OPEN_P
|
||||
%token T_HEADER
|
||||
%token T_CLOSE_P
|
||||
%token T_COMMA
|
||||
%token T_IMPORT
|
||||
%token T_OPAQUE
|
||||
%token T_VOID
|
||||
|
||||
|
||||
%token<id> T_IDENT
|
||||
%token<id> T_HEADERNAME
|
||||
%token<str> T_STRING
|
||||
|
||||
%type<type> type
|
||||
%type<type> typeorvoid
|
||||
%type<type> semitype
|
||||
%type<typename> typename
|
||||
%type<primtype> primtype
|
||||
%type<list> paramlist
|
||||
%type<list> idlist
|
||||
%type<kind> kinddef
|
||||
%type<methprot> methprot
|
||||
%type<dataprot> dataprot
|
||||
%type<list> classbody
|
||||
%type<def> flagsdef
|
||||
%type<def> enumdef
|
||||
%type<def> classdef
|
||||
%type<def> def
|
||||
%type<primtype> object_type
|
||||
%type<list> paramtail
|
||||
%type<param> param
|
||||
%type<str> docstring
|
||||
%type<member> member_def
|
||||
%type<member> data_member_def
|
||||
%type<member> method_def
|
||||
%type<emit_def> emitdef
|
||||
%type<bool> const_def;
|
||||
|
||||
%% /* Grammar rules and actions follow */
|
||||
|
||||
start_symbol: deffile ;
|
||||
|
||||
deffile: /* empty */ | deffile import | deffile modulescope;
|
||||
|
||||
import: T_IMPORT T_IDENT T_END {
|
||||
imports=g_slist_prepend(imports, (gpointer)($2));
|
||||
}
|
||||
|
||||
modulescope: T_MODULE T_IDENT T_OPEN_B {
|
||||
current_module=$2;
|
||||
} modulebody 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;
|
||||
|
||||
decllist: /* empty */ | decllist decl;
|
||||
|
||||
decl: simpledecl | classdecl | opaquedecl | protclassdecl;
|
||||
|
||||
simpledecl: T_TYPE typename T_END {
|
||||
PrimType* t=g_new(PrimType, 1);
|
||||
t->name = $2;
|
||||
t->kind=TYPE_TRANSPARENT;
|
||||
t->decl_header = t->def_header = current_header;
|
||||
put_decl(t);
|
||||
};
|
||||
|
||||
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=NULL;
|
||||
}
|
||||
g_assert(t->kind==TYPE_CLASS);
|
||||
t->def_header=current_header;
|
||||
put_decl(t);
|
||||
}
|
||||
|
||||
classdecl: T_CLASS typename T_END {
|
||||
PrimType* t;
|
||||
t=get_decl($2.module, $2.type);
|
||||
if(!t){
|
||||
t=g_new(PrimType, 1);
|
||||
t->name=$2;
|
||||
t->kind=TYPE_CLASS;
|
||||
t->def_header=NULL;
|
||||
}
|
||||
g_assert(t->kind==TYPE_CLASS);
|
||||
t->decl_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;
|
||||
$$.notnull = FALSE;
|
||||
$$.prim = $2;
|
||||
} | semitype T_POINTER {
|
||||
$$ = $1;
|
||||
$$.indirection++;
|
||||
};
|
||||
|
||||
type: semitype | semitype T_NOTNULLPTR {
|
||||
$$ = $1;
|
||||
$$.indirection++;
|
||||
$$.notnull = TRUE;
|
||||
}
|
||||
|
||||
typeorvoid: type | T_VOID {
|
||||
$$.prim = NULL;
|
||||
$$.indirection = 0;
|
||||
$$.is_const = FALSE;
|
||||
$$.notnull = FALSE;
|
||||
}
|
||||
|
||||
primtype: typename {
|
||||
$$=get_decl($1.module, $1.type);
|
||||
g_assert($$);
|
||||
};
|
||||
|
||||
typename: T_IDENT T_SCOPE T_IDENT {
|
||||
$$.module=$1;
|
||||
$$.type=$3;
|
||||
} | T_IDENT {
|
||||
g_assert(current_module);
|
||||
$$.module=current_module;
|
||||
$$.type=$1;
|
||||
};
|
||||
|
||||
object_type: primtype {
|
||||
$$=$1;
|
||||
g_assert($$->kind==TYPE_CLASS);
|
||||
};
|
||||
|
||||
paramlist: /* empty */ {
|
||||
$$ = NULL;
|
||||
} | param paramtail {
|
||||
$$ = g_slist_prepend($2, $1);
|
||||
};
|
||||
|
||||
paramtail: /* empty */ {
|
||||
$$ = NULL;
|
||||
} | T_COMMA param paramtail {
|
||||
$$ = g_slist_prepend($3, $2);
|
||||
};
|
||||
|
||||
param: type T_IDENT docstring {
|
||||
$$=g_new(Param, 1);
|
||||
$$->method=current_method;
|
||||
$$->doc=$3;
|
||||
$$->name=$2;
|
||||
$$->type=$1;
|
||||
};
|
||||
|
||||
kinddef: T_ABSTRACT {
|
||||
$$ = KIND_ABSTRACT;
|
||||
} | T_DIRECT {
|
||||
$$ = KIND_DIRECT;
|
||||
} | /* empty */ {
|
||||
$$ = KIND_DIRECT;
|
||||
} | T_STATIC {
|
||||
$$ = KIND_STATIC;
|
||||
};
|
||||
|
||||
methprot: T_PROTECTED{
|
||||
$$ = METH_PROTECTED;
|
||||
} | T_PUBLIC {
|
||||
$$ = METH_PUBLIC;
|
||||
};
|
||||
|
||||
dataprot: /* empty */ {
|
||||
$$ = DATA_PROTECTED;
|
||||
} | T_READ_ONLY {
|
||||
$$ = DATA_READONLY;
|
||||
} | T_READ_WRITE {
|
||||
$$ = DATA_READWRITE;
|
||||
};
|
||||
|
||||
emitdef: /* empty */ {
|
||||
$$ = EMIT_NONE;
|
||||
} | T_PRE_EMIT {
|
||||
$$ = EMIT_PRE;
|
||||
} | T_POST_EMIT {
|
||||
$$ = EMIT_POST;
|
||||
};
|
||||
|
||||
docstring: T_STRING {
|
||||
$$ = $1;
|
||||
} | /* empty */ {
|
||||
$$ = NULL;
|
||||
};
|
||||
|
||||
|
||||
idlist: T_IDENT {
|
||||
$$ = g_slist_prepend(NULL, (gpointer)($1));
|
||||
} | idlist T_COMMA T_IDENT {
|
||||
$$ = g_slist_append($1, (gpointer)($3));
|
||||
};
|
||||
|
||||
def: classdef | enumdef | flagsdef;
|
||||
|
||||
enumdef: T_ENUM primtype T_OPEN_B idlist T_CLOSE_B docstring T_END {
|
||||
EnumDef* d=g_new(EnumDef, 1);
|
||||
g_assert($2->kind==TYPE_TRANSPARENT);
|
||||
d->alternatives = $4;
|
||||
$$=DEF(d);
|
||||
$$->klass=&enum_class;
|
||||
$$->type=$2;
|
||||
$$->doc=$6;
|
||||
};
|
||||
|
||||
flagsdef: T_FLAGS primtype T_OPEN_B idlist T_CLOSE_B docstring T_END {
|
||||
FlagsDef* d=g_new(FlagsDef, 1);
|
||||
g_assert($2->kind==TYPE_TRANSPARENT);
|
||||
d->flags = $4;
|
||||
$$=DEF(d);
|
||||
$$->klass=&flags_class;
|
||||
$$->type=$2;
|
||||
$$->doc=$6;
|
||||
};
|
||||
|
||||
classdef: T_CLASS object_type T_INHERITANCE object_type docstring T_OPEN_B {
|
||||
current_class=g_new(ObjectDef, 1);
|
||||
} classbody T_CLOSE_B T_END {
|
||||
current_class->parent = $4;
|
||||
current_class->members = $8;
|
||||
$$=DEF(current_class);
|
||||
current_class=NULL;
|
||||
$$->klass=&object_class;
|
||||
$$->type = $2;
|
||||
$$->doc = $5;
|
||||
};
|
||||
|
||||
member_def: data_member_def | method_def;
|
||||
|
||||
|
||||
data_member_def: dataprot kinddef type T_IDENT emitdef docstring T_END {
|
||||
DataMember* m = g_new(DataMember, 1);
|
||||
m->prot = $1;
|
||||
m->type = $3;
|
||||
$$ = MEMBER(m);
|
||||
$$->membertype = MEMBER_DATA;
|
||||
$$->kind = $2;
|
||||
$$->name = $4;
|
||||
/* $$->emit = $5; */
|
||||
$$->doc = $6;
|
||||
};
|
||||
|
||||
method_def: methprot kinddef typeorvoid T_IDENT T_OPEN_P {
|
||||
current_method = g_new(Method, 1);
|
||||
} paramlist T_CLOSE_P const_def emitdef docstring T_END {
|
||||
current_method = NULL;
|
||||
current_method->prot = $1;
|
||||
current_method->ret_type = $3;
|
||||
current_method->self_const = $9;
|
||||
current_method->params = $7;
|
||||
$$=MEMBER(current_method);
|
||||
current_method=NULL;
|
||||
$$->membertype = MEMBER_METHOD;
|
||||
$$->kind = $2;
|
||||
$$->name = $4;
|
||||
/* $$->emit = $10; */
|
||||
$$->doc = $11;
|
||||
};
|
||||
|
||||
const_def: T_CONST {
|
||||
$$ = TRUE;
|
||||
} | /* empty */ {
|
||||
$$ = FALSE;
|
||||
};
|
||||
|
||||
classbody: /* empty */ {
|
||||
$$ = NULL;
|
||||
} | classbody member_def{
|
||||
$$ = g_slist_prepend($1, $2);
|
||||
};
|
||||
|
||||
%%
|
||||
#define YYDEBUG 1
|
||||
|
||||
GHashTable* type_hash;
|
||||
GHashTable* class_hash;
|
||||
|
||||
|
||||
int yyerror (char* s){
|
||||
g_error ("Parser error: %s", s);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue