From d74bf3623e3d68998c4cdce39f10755efb6dc059 Mon Sep 17 00:00:00 2001 From: Lauri Alanko Date: Fri, 20 Nov 1998 23:21:40 +0000 Subject: [PATCH] It actually runs now, with a zillion caveats, but anyway.. Still have to do lotsa things for serious use.. --- tools/gcg/ChangeLog | 5 ++ tools/gcg/Makefile.am | 6 +- tools/gcg/configure.in | 3 +- tools/gcg/db.c | 18 +++-- tools/gcg/ex/Makefile.am | 22 ++++++ tools/gcg/ex/README | 1 + tools/gcg/ex/file_ostream.c | 24 ++++++ tools/gcg/ex/file_ostream.gc | 15 ++++ tools/gcg/ex/ostream.c | 16 ++++ tools/gcg/ex/ostream.gc | 12 +++ tools/gcg/ex/stream.gh | 14 ++++ tools/gcg/gcg.c | 148 +++++++++++++++++++++++++---------- tools/gcg/gcg.h | 5 +- tools/gcg/gh/gcg.gh | 11 +++ tools/gcg/gh/glib.gh | 30 +++++++ tools/gcg/gimpimage.def | 43 ---------- tools/gcg/lexer.l | 18 +++-- tools/gcg/marshall.c | 15 +++- tools/gcg/output.c | 111 ++++++++++++++++---------- tools/gcg/output.h | 6 ++ tools/gcg/output_enum.c | 4 +- tools/gcg/output_flags.c | 4 +- tools/gcg/output_object.c | 45 ++++++----- tools/gcg/parser.y | 75 ++++++++++++++---- tools/gcg/pnode.c | 93 +++++++++------------- tools/gcg/pnode.h | 6 +- 26 files changed, 506 insertions(+), 244 deletions(-) create mode 100644 tools/gcg/ex/Makefile.am create mode 100644 tools/gcg/ex/README create mode 100644 tools/gcg/ex/file_ostream.c create mode 100644 tools/gcg/ex/file_ostream.gc create mode 100644 tools/gcg/ex/ostream.c create mode 100644 tools/gcg/ex/ostream.gc create mode 100644 tools/gcg/ex/stream.gh create mode 100644 tools/gcg/gh/gcg.gh create mode 100644 tools/gcg/gh/glib.gh delete mode 100644 tools/gcg/gimpimage.def diff --git a/tools/gcg/ChangeLog b/tools/gcg/ChangeLog index a18164b0cb..db1573957d 100644 --- a/tools/gcg/ChangeLog +++ b/tools/gcg/ChangeLog @@ -1,3 +1,8 @@ +1998-11-21 Lauri Alanko + + * It actually runs now, with a zillion caveats, but anyway.. + Still have to do lotsa things for serious use.. + 1998-11-20 Lauri Alanko * Again modified the formatting stuff. Some preliminary header diff --git a/tools/gcg/Makefile.am b/tools/gcg/Makefile.am index dfd8c54f57..f2f1e4c06e 100644 --- a/tools/gcg/Makefile.am +++ b/tools/gcg/Makefile.am @@ -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 diff --git a/tools/gcg/configure.in b/tools/gcg/configure.in index f727e0d972..15334637a4 100644 --- a/tools/gcg/configure.in +++ b/tools/gcg/configure.in @@ -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]) diff --git a/tools/gcg/db.c b/tools/gcg/db.c index 66842a98a2..e2c81c4c17 100644 --- a/tools/gcg/db.c +++ b/tools/gcg/db.c @@ -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){ diff --git a/tools/gcg/ex/Makefile.am b/tools/gcg/ex/Makefile.am new file mode 100644 index 0000000000..73d49b4021 --- /dev/null +++ b/tools/gcg/ex/Makefile.am @@ -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 + diff --git a/tools/gcg/ex/README b/tools/gcg/ex/README new file mode 100644 index 0000000000..d6d9eca5bc --- /dev/null +++ b/tools/gcg/ex/README @@ -0,0 +1 @@ +This is just a bunch of miscellaneous test/example classes. diff --git a/tools/gcg/ex/file_ostream.c b/tools/gcg/ex/file_ostream.c new file mode 100644 index 0000000000..cf40f7005a --- /dev/null +++ b/tools/gcg/ex/file_ostream.c @@ -0,0 +1,24 @@ +#include + +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; +} diff --git a/tools/gcg/ex/file_ostream.gc b/tools/gcg/ex/file_ostream.gc new file mode 100644 index 0000000000..0bda113c96 --- /dev/null +++ b/tools/gcg/ex/file_ostream.gc @@ -0,0 +1,15 @@ +#include "stream.gh" + +package{ + module { + foreign FILE; + } +} + +module Ex.FileOstream; + + +class FileOstream : Ostream{ + .FILE* file; + public static FileOstream* open(g.char* filename); +} diff --git a/tools/gcg/ex/ostream.c b/tools/gcg/ex/ostream.c new file mode 100644 index 0000000000..7ef4175009 --- /dev/null +++ b/tools/gcg/ex/ostream.c @@ -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; +} + diff --git a/tools/gcg/ex/ostream.gc b/tools/gcg/ex/ostream.gc new file mode 100644 index 0000000000..e31216572c --- /dev/null +++ b/tools/gcg/ex/ostream.gc @@ -0,0 +1,12 @@ +#include + +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 (); +} diff --git a/tools/gcg/ex/stream.gh b/tools/gcg/ex/stream.gh new file mode 100644 index 0000000000..dfd19da497 --- /dev/null +++ b/tools/gcg/ex/stream.gh @@ -0,0 +1,14 @@ +#include + +package Ex { + module Ostream{ + class Ostream; + } + module FileOstream{ + class FileOstream; + } + module StringOstream{ + class StringOstream; + } +} + diff --git a/tools/gcg/gcg.c b/tools/gcg/gcg.c index 23bab01c1b..d038cdaea1 100644 --- a/tools/gcg/gcg.c +++ b/tools/gcg/gcg.c @@ -1,10 +1,8 @@ -#include "gcg.h" -#include "parser.h" #include -#include - -#define __USE_POSIX2 - +#include +#include +#include "gcg.h" +#include "parse.h" #include #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 \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; } diff --git a/tools/gcg/gcg.h b/tools/gcg/gcg.h index 1c43511583..77f1b0cf23 100644 --- a/tools/gcg/gcg.h +++ b/tools/gcg/gcg.h @@ -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; }; diff --git a/tools/gcg/gh/gcg.gh b/tools/gcg/gh/gcg.gh new file mode 100644 index 0000000000..7daa771d9c --- /dev/null +++ b/tools/gcg/gh/gcg.gh @@ -0,0 +1,11 @@ + +package Gtk{ + module { + class Object; + } +} + +#include + +root Gtk.Object; + diff --git a/tools/gcg/gh/glib.gh b/tools/gcg/gh/glib.gh new file mode 100644 index 0000000000..c6102a7583 --- /dev/null +++ b/tools/gcg/gh/glib.gh @@ -0,0 +1,30 @@ +package g { + module { + integer int; + integer uint; + integer boolean; + character char; + character uchar; + } +} + +package G { + module { + 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; + } +} diff --git a/tools/gcg/gimpimage.def b/tools/gcg/gimpimage.def deleted file mode 100644 index b26ea2a513..0000000000 --- a/tools/gcg/gimpimage.def +++ /dev/null @@ -1,43 +0,0 @@ -// this is just a simple test input file - -#include - -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); -} diff --git a/tools/gcg/lexer.l b/tools/gcg/lexer.l index 99d7af18d3..4804de3f6d 100644 --- a/tools/gcg/lexer.l +++ b/tools/gcg/lexer.l @@ -2,8 +2,9 @@ %option yylineno %{ -#include "gcg.h" +#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)); diff --git a/tools/gcg/marshall.c b/tools/gcg/marshall.c index c7d567484d..8d5a2bf420 100644 --- a/tools/gcg/marshall.c +++ b/tools/gcg/marshall.c @@ -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 diff --git a/tools/gcg/output.c b/tools/gcg/output.c index 4c6d755ba4..2351d7cbe8 100644 --- a/tools/gcg/output.c +++ b/tools/gcg/output.c @@ -5,42 +5,41 @@ PNode* p_c_ident(Id id){ PNode* n; - gchar* c; - gchar* s; - - c=s=g_strdup(id); - - while(*c){ - *c=tolower(*c); - if(!isalnum(*c)) - *c='_'; - c++; + gint i = 0; + GString* s = g_string_new(NULL); + + 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; - - c=s=g_strdup(id); - while(*c){ - *c=toupper(*c); - if(!isalnum(*c)) - *c='_'; - c++; + gint i = 0; + GString* s = g_string_new(NULL); + + 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)); diff --git a/tools/gcg/output.h b/tools/gcg/output.h index dd1731b901..6f27e0e381 100644 --- a/tools/gcg/output.h +++ b/tools/gcg/output.h @@ -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); + + diff --git a/tools/gcg/output_enum.c b/tools/gcg/output_enum.c index 3f133ad2d6..b54feb195b 100644 --- a/tools/gcg/output_enum.c +++ b/tools/gcg/output_enum.c @@ -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)); } diff --git a/tools/gcg/output_flags.c b/tools/gcg/output_flags.c index ec2080307b..14ff94ff9a 100644 --- a/tools/gcg/output_flags.c +++ b/tools/gcg/output_flags.c @@ -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); } diff --git a/tools/gcg/output_object.c b/tools/gcg/output_object.c index 26aae38eb8..e8fb39f79f 100644 --- a/tools/gcg/output_object.c +++ b/tools/gcg/output_object.c @@ -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); } diff --git a/tools/gcg/parser.y b/tools/gcg/parser.y index f02307b57c..fbf138c480 100644 --- a/tools/gcg/parser.y +++ b/tools/gcg/parser.y @@ -1,13 +1,17 @@ %{ #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; + + %} @@ -71,11 +75,14 @@ static GSList* imports_list; %token T_SIGNAL %token T_FOREIGN %token T_PACKAGE +%token T_ROOT +%token T_CHAR %token T_IDENT %token T_HEADERNAME %token T_STRING +%type maybeident %type ident %type headerdef %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; } diff --git a/tools/gcg/pnode.c b/tools/gcg/pnode.c index ba3ca98b60..fa6a1c813e 100644 --- a/tools/gcg/pnode.c +++ b/tools/gcg/pnode.c @@ -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; diff --git a/tools/gcg/pnode.h b/tools/gcg/pnode.h index a30ea9df24..96c6b5d129 100644 --- a/tools/gcg/pnode.h +++ b/tools/gcg/pnode.h @@ -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);