Commit 91f86846 authored by Lauri Alanko's avatar Lauri Alanko

Initially committed to CVS.

parent 9005889d
1998-10-21 Lauri Alanko <la@iki.fi>
* Initially committed to CVS
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
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
#!/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
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)
#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);
}
#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;
}
#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
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;
};
};
%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];
%%
#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;
}
#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);
}
#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);