]> git.draconx.ca Git - gob-dx.git/commitdiff
Release 0.93.0 v0.93.0
authorGeorge Lebl <jirka@5z.com>
Mon, 28 Feb 2000 20:15:00 +0000 (12:15 -0800)
committerNick Bowler <nbowler@draconx.ca>
Tue, 19 Feb 2019 17:19:20 +0000 (12:19 -0500)
18 files changed:
ChangeLog
NEWS
configure
configure.in
doc/gob.1.in
examples/README
examples/my-person.gob
gob.spec
src/checks.c
src/checks.h
src/main.c
src/main.h
src/out.c
src/parse.c
src/parse.y
src/test.gob
src/tree.c
src/tree.h

index f95e8ed2f8f8136c4a459cfb52daca506a55294b..7a85c7d373d206a1ada40742e758794366593887 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+Mon Feb 28 02:45:27 2000  George Lebl <jirka@5z.com>
+
+       * Release 0.93.0
+
+Sun Feb 27 20:59:45 2000  George Lebl <jirka@5z.com>
+
+       * src/parse.y,doc/gob.1.in: For stringlink, just return a pointer on
+         get rather then strduping as that is 1) consistent with objectlink
+         and 2) more flexible.
+
+Sun Feb 27 20:38:19 2000  George Lebl <jirka@5z.com>
+
+       * src/{main.c,tree.[ch],parse.y}: add the arbitrary destruction handler
+         for data members
+
+       * doc/gob.1.in: updated and fixed up
+
+       * configure.in,NEWS,examples/{README,my-person2.gob}: change version
+         to 0.93.0
+
+Sun Feb 27 18:37:57 2000  George Lebl <jirka@5z.com>
+
+       * NEWS,doc/gob.1.in,examples/{README,my-person.gob,my-person2.gob}:
+         update of docs and examples to include the new features and minor
+         fixups
+
+Sun Feb 27 04:41:41 2000  George Lebl <jirka@5z.com>
+
+       * src/main.c: make the output nicer for classes with no methods
+         better typechecking in get/set_arg, fix a couple of C++ issues,
+
+       * src/{main.c,parse.y,tree.[ch]}: automatic linking of arguments to
+         data members.  Also alow empty statements inside a class.  Also
+         add automatic data member destruction for pointer data, and
+         automatic initialization for any data member.
+
+       * src/main.[ch],src/out.c: add --no-lines which inhibits printing
+         of #line things to output files
+
+       * doc/gob.1.in: update for the above
+
 Fri Feb 25 15:21:47 2000  George Lebl <jirka@5z.com>
 
        * Release 0.92.4
diff --git a/NEWS b/NEWS
index ed9b415737c94c59b4fc13f3031766361d78ef93..8d1df7bded9beea77910293b2ff8e38ec8f36f95 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,11 @@
+0.93.0
+       * data member initialization
+       * pointer data member destruction
+       * automatic argument to data member linking for simple cases
+       * other minor fixes/improvements
+
 0.92.4
-        * -n flag (Dave Dunkin)
+       * -n flag (Dave Dunkin)
        * all and alltop code sections (Dave Dunkin)
        * GTK_RUN_ flags for signals
        * self casting macros
index 31319a1bc9e65c7c439ade15dd129b3c5f07e319..dc43560e7f303a9d5328f9b357643c4e7bc73dbf 100755 (executable)
--- a/configure
+++ b/configure
@@ -703,7 +703,7 @@ fi
 
 PACKAGE=gob
 
-VERSION=0.92.4
+VERSION=0.93.0
 
 if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
   { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
index 22d78a16db73b3f83505df4e7d97e72e83033fea..96aa7c94c1c1903f754c21b63d443fa3f45a8561 100644 (file)
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.2)
 AC_INIT(src/tree.h)
 AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(gob,0.92.4)
+AM_INIT_AUTOMAKE(gob,0.93.0)
 
 if test -f ../NOINST_GOB ; then
   DOINSTGOB=
index 6717d3e2a89cbeace89fe7367c710e33217d0f1a..df1472bb2635388ea692b713549c6bf2c9b71e02 100644 (file)
@@ -230,14 +230,86 @@ In case you use the \fB--no-private-header\fR option, no
 private header file is created and you can only access the _priv pointer
 below the class definition in the .gob file.
 .PP
-The fourth type is an argument type.  It is a named data member which
-is one of the features of the GTK+ object system.  You need to define a get
-and a set handler.  They are fragments of C code that will be used to 
-get the value or set the value of the argument.  Inside them you can use the
-define ARG to which you assign the data or get the data.  You can also use
-the identifier "self" as pointer to the object instance.  The type is
-defined as one of the gtk type enums, but without the GTK_TYPE_ prefix.
-For example:
+Automatic Initialization (0.93.0 and higher only):
+.PP
+You can automatically initialize the public private and protected data members
+without having to add an init method.  The advantage here is that
+initialization is kept close to the definition of the data member and thus
+it's easier to check.  To do this, just add a '=' followed by a number or
+a token.  It is also possible to include arbitrary C code for more elaborate
+initializations by putting it all in curly braces.  Note that the curly braces
+will not be printed into the output, but since gob does not C parsing it needs
+them to figure out where the C code ends.  The code will be inserted into the
+init method, above the user defined body.  So for example the following
+will initialize an integer to -1 and a string with a newly allocated string
+of "hello".
+.nf
+
+  public int foo = -1;
+  private char *bar = {g_strdup("hello")};
+
+.fi
+.PP
+Automatic Destruction (0.93.0 and higher only):
+.PP
+Most data stored as pointers needs to have a function called when the object
+is destroyed, to either free it or give up a reference.  Gob will let you
+define a function to be called on the data the object is destroyed.  This is
+achieved by putting 'destroywith' followed by a function name after the
+variable definition.  It is only called if the data you defined this on
+is not NULL, so you cans specify functions which do not handle NULL.  It
+is very much like the GDestroyNotify function used in GTK+ and glib in many
+places.  Unlike many other places, gob will not enforce any kind of type
+safety here so be a little bit more careful.  Any function you give it will
+be called as a "void function(void *)".  It will in fact be cast into such
+a form before called.  This is to avoid spurious warnings for gtk calls to
+subclass methods.  The function needs not be of that form, it just has to
+take one argument which is the pointer to the data.  You should also not
+define this on any non-pointer data as the results may be undefined.
+Example:
+.nf
+
+  public Gtk:Widget *window = NULL
+          destroywith gtk_widget_destroy;
+  public char *foo = {g_strdup("bar")}
+          destroywith g_free;
+
+.fi
+Note that the function name you give must be a real function and not macro.
+Also note that this is always called in the "finalize" method of GtkObject.
+.PP
+Sometimes you may want to run arbitrary code on destruction.  While this can
+be perfectly well done in the destroy handler.  Depending on the style you
+may want to include all destruction/initialization code together with the
+definition of the data member.  Thus you may want to put arbitrary code which
+will then be inserted into the "finalize" method of GtkObject.  This can be
+done with the "destroy" keyword followed by arbitrary code in curly braces.  
+Inside this code a macro called VAR will be define which refers to your
+variable.  So for example destroying a GString can be either done with
+a helper routine or the following code:
+.nf
+
+  public GString *string = {g_string_new(NULL)}
+          destroy {
+                 if(VAR) g_string_free(VAR, TRUE);
+         };
+
+.fi
+The thing to remember with these is that there are many ways to do this
+and you'd better be consistent in your code in how you use the above things.
+Also defining a helper routine that will do the destruction will be a nicer
+thing to do if that's a possibility.  The "destroy" keyword with code does
+take up more space in the file and it may become more cluttered.
+.PP
+GTK+ Arguments:
+.PP
+The fourth type of a data member an argument type.  It is a named data member
+which is one of the features of the GTK+ object system.  You need to define a
+get and a set handler.  They are fragments of C code that will be used to get
+the value or set the value of the argument.  Inside them you can use the define
+ARG to which you assign the data or get the data.  You can also use the
+identifier "self" as pointer to the object instance.  The type is defined as
+one of the gtk type enums, but without the GTK_TYPE_ prefix.  For example:
 .nf
 
   public int height;
@@ -294,6 +366,79 @@ right after the GTK+ type.  Example:
 
 .fi
 .PP
+Sometimes it can become tiresome to type in the set and get handlers if
+they are trivial.  So gob since version 0.93.0 provides automatic argument
+linking to data members.  There are three different cases it handles, direct
+link (keyword 'link'), string linking (keyword 'stringlink') and object
+linking (keyword 'objectlink').  You just place the keyword after the argument
+name instead of the get/set handlers.  It will link to a data member of the
+same name that was defined earlier in the input file.  Best is to see examples:
+.nf
+
+  public int foo;
+  argument INT foo link;
+
+.fi
+is just like
+.nf
+
+  public int foo;
+  argument INT (type int) foo
+  get { ARG = self->foo; }
+  set { self->foo = ARG; };
+
+.fi
+Similiarly,
+.nf
+
+  private char * foo;
+  argument POINTER foo stringlink;
+
+.fi
+is just like
+.nf
+
+  private char * foo;
+  argument POINTER (type char *) foo
+  get {
+        ARG = self->_priv->foo;
+  } set {
+       g_free(self->_priv->foo);
+        self->_priv->foo = g_strdup(ARG);
+  }
+
+.fi
+And for the objectlink we would have:
+.nf
+
+  public Gtk:Object * foo;
+  argument POINTER foo objectlink;
+
+.fi
+is just like
+.nf
+
+  protected Gtk:Object * foo;
+  argument POINTER (type Gtk:Object *) foo
+  get {
+        ARG = self->foo;
+  } set {
+        if(self->foo)
+                gtk_object_unref(self->foo);
+        self->foo = ARG;
+        if(self->foo)
+                gtk_object_ref(self->foo);
+  }
+
+.fi
+.PP
+As you see it will handle NULLs correctly (for the string, g_free and g_strdup
+handle NULLs).  And it will also handle private, protected and public members.
+Also you should notice that when the get is used, only a pointer is always
+returned for both objectlink and strinklink.  So you should treat the returned
+value with care and never free it (and notice that it will only be around
+until you set the argument to something else or destroy the object).
+.PP
 Methods:
 .PP
 There is a whole array of possible methods.  The three normal,
@@ -312,7 +457,7 @@ body.  This will define an empty function.  You can't do this for non-void
 regular public, private or protected methods, however it is acceptable for
 non-void virtual, signal and override methods.
 .PP
-Argument lists:
+Function argument lists:
 .PP
 For all but the init and class_init methods, you use the
 following syntax for arguments.  The first argument can be just "self",
@@ -575,6 +720,11 @@ methods.  You shouldn't generally use 3 underscores even in override method
 argument lists and virtual and signal method names as it might confuse the
 PARENT_HANDLER macro.  In fact avoiding all names with three underscores is
 the best policy when working with gob.
+.PP
+There are a couple of defines which you shouldn't be redefining in the code
+or other headers.  These are SELF, IS_SELF, SELF_CLASS, ARG, VAR,
+PARENT_HANDLER, GET_NEW, GOB_VERSION_MAJOR, GOB_VERSION_MINOR and
+GOB_VERSION_PATCHLEVEL.
 
 .SH USING GTK-DOC STYLE INLINE DOCUMENTATION
 .PP
index d5be66583e83893726fab703c5cb9212041f4837..1eebe5533d180299a5f4ac7b39c2ca8e70ed5692 100644 (file)
@@ -12,3 +12,6 @@ gtk-button-count.gob  An example showing how simple it is to derive
 my-person.gob          A simple file which can store some identity
                        information about a person, it shows arguments,
                        signals and others.
+
+my-person2.gob         The same as above but using automatic initialization,
+                       destruction and argument linking features of 0.93.0+
index f09b1511ae205a005ecbc213e18a892284389736..06a0aaaa5608534fd186b1803167632e47df0c90 100644 (file)
@@ -1,4 +1,8 @@
-require 0.92.1
+requires 0.92.1
+
+/* This will work with an older version (0.92.1 specifically), if you want
+ * to see a version with automatic argument<->datamember linking, automatic
+ * initialization and destruction, look at my-person2.gob */
 
 %{
 #include <time.h>
@@ -15,17 +19,13 @@ class My:Person from Gtk:Object {
 
        argument POINTER (type char *) name
        get {
-               if(self->name)
-                       ARG = g_strdup(self->name);
-               else
-                       ARG = NULL;
+               /* note that strdup handles NULL correctly */
+               ARG = g_strdup(self->name);
        }
        set {
+               /* note that strdup handles NULL correctly */
                g_free(self->name);
-               if(ARG)
-                       self->name = g_strdup(ARG);
-               else
-                       self->name = NULL;
+               self->name = g_strdup(ARG);
        };
 
        argument LONG dob get { ARG = self->dob; } set { self->dob = ARG; };
@@ -80,6 +80,15 @@ class My:Person from Gtk:Object {
                self->_priv->rounds_in_shotgun--;
 
                /* death is imminent if we shoot oneself in the head */
-               death(self,(long)time(NULL));
+               death(self, (long)time(NULL));
+       }
+
+       /* override the destroy signal where we destroy data we need to free */
+       override (Gtk:Object)
+       void
+       destroy (Gtk:Object *self (check null type))
+       {
+               g_free(MY_PERSON(self)->name);
+               PARENT_HANDLER(self);
        }
 }
index 886cfc4dc6ce667f1b8d49179a4508ad8247c166..ad826609cf6d743705534bb5251855c615e39d24 100644 (file)
--- a/gob.spec
+++ b/gob.spec
@@ -1,4 +1,4 @@
-%define  ver     0.92.4
+%define  ver     0.93.0
 %define  rel     1
 %define  prefix  /usr
 
index 73b10d88b3aa20beb1f3f05fdfa5064a20da8a97..80602d1f16b189aba043b6ab6844371aa6be3b7a 100644 (file)
@@ -396,3 +396,35 @@ count_protecteds(Class *c)
        }
        return num;
 }
+
+int
+count_destructors(Class *c)
+{
+       int num = 0;
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == VARIABLE_NODE) {
+                       Variable *v = (Variable *)n;
+                       if(v->destructor)
+                               num++;
+               }
+       }
+       return num;
+}
+
+int
+count_initializers(Class *c)
+{
+       int num = 0;
+       GList *l;
+       for(l=c->nodes;l;l=g_list_next(l)) {
+               Node *n = l->data;
+               if(n->type == VARIABLE_NODE) {
+                       Variable *v = (Variable *)n;
+                       if(v->initializer)
+                               num++;
+               }
+       }
+       return num;
+}
index 53d19d504e55f744c696357492c57e287c965b8b..b6e9171f261ee8e6521b649490cfc8a561e150a1 100644 (file)
@@ -39,5 +39,7 @@ int count_arguments(Class *c);
 int count_overrides(Class *c);
 int count_privates(Class *c);
 int count_protecteds(Class *c);
+int count_destructors(Class *c);
+int count_initializers(Class *c);
 
 #endif
index dedf432f1e327c2e2f19f0c5564586fa61e3a87e..226e8211265b90627b0dee0826271225ee984bce 100644 (file)
@@ -63,6 +63,8 @@ static int arguments = 0; /* number of named arguments */
 static int overrides = 0; /* number of override methods */
 static int privates = 0; /* number of private data members */
 static int protecteds = 0; /* number of protected methods */
+static int destructors = 0; /* number of variable destructors */
+static int initializers = 0; /* number of variable initializers */
 
 static gboolean made_aliases = FALSE;  /* if we made any shorthand aliases
                                          and need the REALLY UGLY HACK to
@@ -83,6 +85,7 @@ gboolean always_private_header = FALSE;
 gboolean no_private_header = FALSE;
 gboolean no_extern_c = FALSE;
 gboolean no_write = FALSE;
+gboolean no_lines = FALSE;
 
 static void
 make_bases(void)
@@ -214,6 +217,27 @@ print_method(FILE *fp, char *typeprefix, char *nameprefix,
        out_printf(fp, ")%s", postfix); 
 }
 
+static gboolean
+any_method_to_alias(Class *c)
+{
+       GList *li;
+       
+       for(li=c->nodes;li;li=g_list_next(li)) {
+               Node *node = li->data;
+               if(node->type == METHOD_NODE) {
+                       Method *m = (Method *)node;
+                       
+                       if(m->method == INIT_METHOD ||
+                          m->method == CLASS_INIT_METHOD ||
+                          m->method == OVERRIDE_METHOD)
+                               continue;
+
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
 
 static void
 make_method_gnu_aliases(Class *c)
@@ -685,6 +709,7 @@ add_enums(Class *c)
                out_printf(out,
                           "static guint object_signals[LAST_SIGNAL] = {0};\n\n");
 
+       out_printf(out, "/* pointer to the class of our parent */\n");
        out_printf(out, "static %sClass *parent_class = NULL;\n\n",ptypebase);
 }
 
@@ -842,7 +867,7 @@ add_signals(Class *c)
                flags = make_run_signal_flags(m, last);
                out_printf(out,"\tobject_signals[%s_SIGNAL] =\n"
                        "\t\tgtk_signal_new (\"%s\",\n"
-                       "\t\t\%s,\n"
+                       "\t\t\t(GtkSignalRunType)(%s),\n"
                        "\t\t\tgtk_object_class->type,\n"
                        "\t\t\tGTK_SIGNAL_OFFSET (%sClass, %s),\n"
                        "\t\t\t%s,\n"
@@ -970,9 +995,9 @@ make_arguments(Class *c)
                        "\t\tGTK_TYPE_%s,\n"
                        "\t\t%s,\n"
                        "\t\tARG_%s);\n",
-                       typebase,a->name,a->gtktype,flags->str,s);
+                       typebase, a->name, a->gtktype, flags->str, s);
                g_free(s);
-               g_string_free(flags,TRUE);
+               g_string_free(flags, TRUE);
        }
        
        out_printf(out,
@@ -980,6 +1005,32 @@ make_arguments(Class *c)
                   "\tgtk_object_class->get_arg = ___object_get_arg;\n");
 }
 
+static void
+print_initializer(Method *m, Variable *v)
+{
+       char *root;
+
+       if(v->initializer == NULL)
+               return;
+
+       if(v->scope == PRIVATE_SCOPE)
+               root = g_strconcat(((FuncArg *)m->args->data)->name,
+                                  "->_priv", NULL);
+       else
+               root = g_strdup(((FuncArg *)m->args->data)->name);
+
+       if(v->initializer_line > 0)
+               out_addline_infile(out, v->initializer_line);
+
+       out_printf(out, "\t%s->%s = %s;\n",
+                  root, v->id, v->initializer);
+
+       if(v->initializer_line > 0)
+               out_addline_outfile(out);
+
+       g_free(root);
+}
+
 static void
 add_inits(Class *c)
 {
@@ -991,25 +1042,36 @@ add_inits(Class *c)
                        continue;
                m = (Method *)n;
                if(m->method == INIT_METHOD) {
-                       if(m->line_no>0)
+                       if(m->line_no > 0)
                                out_addline_infile(out,m->line_no);
                        print_method(out, "static ", "\n", "", " ", "\n",
                                     m, FALSE, FALSE);
-                       if(m->line_no>0)
+                       if(m->line_no > 0)
                                out_addline_outfile(out);
                        out_printf(out,"{\n");
-                       if(privates>0) {
+                       if(privates > 0) {
                                out_printf(out,"\t%s->_priv = "
-                                          "g_new0 (%sPrivate,1);\n",
+                                          "g_new0 (%sPrivate, 1);\n",
                                           ((FuncArg *)m->args->data)->name,
                                           typebase);
                        }
+                       if(initializers > 0) {
+                               GList *li;
+                               for(li = ((Class *)class)->nodes;
+                                   li != NULL;
+                                   li = li->next) {
+                                       Node *n = li->data;
+                                       if(n->type != VARIABLE_NODE)
+                                               continue;
+                                       print_initializer(m, (Variable *)n);
+                               }
+                       }
                } else if(m->method == CLASS_INIT_METHOD) {
-                       if(m->line_no>0)
+                       if(m->line_no > 0)
                                out_addline_infile(out, m->line_no);
                        print_method(out, "static ", "\n", "", " ", "\n",
                                     m, FALSE, FALSE);
-                       if(m->line_no>0)
+                       if(m->line_no > 0)
                                out_addline_outfile(out);
                        out_printf(out,"{\n");
                        if(signals>0 ||
@@ -1056,7 +1118,7 @@ add_inits(Class *c)
 }
 
 static void
-add_getset_arg(Class *c, int is_set)
+add_getset_arg(Class *c, gboolean is_set)
 {
        GList *li;
        out_printf(out,"\nstatic void\n"
@@ -1089,14 +1151,39 @@ add_getset_arg(Class *c, int is_set)
                        continue;
                s = g_strdup(a->name);
                g_strup(s);
-               out_printf(out,"\tcase ARG_%s:\n"
-                       "#define ARG (GTK_VALUE_%s(*arg))\n"
-                       "\t\t{\n",
-                       s,a->gtktype);
+               if(is_set && a->atype) {
+                       char *cast = get_type(a->atype, TRUE);
+                       out_printf(out, "\tcase ARG_%s:\n", s);
+                       if(no_gnu || for_cpp) {
+                               out_printf(out, "#define ARG "
+                                          "((%s)GTK_VALUE_%s(*arg))\n",
+                                          cast, a->gtktype);
+                       } else {
+                               out_printf(out, "#ifdef __GNUC__\n");
+                               out_printf(out, "#define ARG "
+                                          "({%s foo = GTK_VALUE_%s(*arg); "
+                                            "foo; })\n",
+                                          cast, a->gtktype);
+                               out_printf(out,"#else /* __GNUC__ */\n");
+                               out_printf(out, "#define ARG "
+                                          "((%s)GTK_VALUE_%s(*arg))\n",
+                                          cast, a->gtktype);
+                               out_printf(out,"#endif /* __GNUC__ */\n\n");
+                       }
+                       out_printf(out, "\t\t{\n");
+                       g_free(cast);
+               } else {
+                       out_printf(out, "\tcase ARG_%s:\n"
+                                  "#define ARG (GTK_VALUE_%s(*arg))\n"
+                                  "\t\t{\n",
+                                  s, a->gtktype);
+               }
                g_free(s);
-               out_addline_infile(out,line_no);
+               if(line_no > 0)
+                       out_addline_infile(out, line_no);
                out_printf(out,"%s\n",cbuf);
-               out_addline_outfile(out);
+               if(line_no > 0)
+                       out_addline_outfile(out);
                out_printf(out,"\t\t}\n\t\tbreak;\n"
                        "#undef ARG\n");
        }
@@ -1116,7 +1203,7 @@ print_checks(Method *m, FuncArg *fa)
                Check *ch = li->data;
                char *s;
                /* point to the method prot in .gob for failed checks */
-               if(m->line_no>0)
+               if(m->line_no > 0)
                        out_addline_infile(out,m->line_no);
                if(is_void)
                        out_printf(out,"\tg_return_if_fail (");
@@ -1157,11 +1244,11 @@ print_checks(Method *m, FuncArg *fa)
                        break;
                }
                if(is_void)
-                       out_printf(out,");\n");
+                       out_printf(out, ");\n");
                else {
-                       out_printf(out,", (");
-                       print_type(out,m->mtype,TRUE);
-                       out_printf(out,")%s);\n",
+                       out_printf(out, ", (");
+                       print_type(out, m->mtype, TRUE);
+                       out_printf(out, ")%s);\n",
                                m->onerror?m->onerror:"0");
                }
        }
@@ -1181,20 +1268,76 @@ print_preconditions(Method *m)
                out_addline_outfile(out);
 }
 
+static void
+print_destructor(char *self_id, Variable *v)
+{
+       char *root;
+
+       if(v->destructor == NULL)
+               return;
+
+       if(v->scope == PRIVATE_SCOPE)
+               root = g_strconcat(self_id, "->_priv", NULL);
+       else
+               root = g_strdup(self_id);
+
+       if(v->destructor_simple) {
+               if(v->destructor_line > 0)
+                       out_addline_infile(out, v->destructor_line);
+
+               out_printf(out, "\tif(%s->%s) "
+                          "((*(void (*)(void *))%s)) (%s->%s);\n",
+                          root, v->id, v->destructor, root, v->id);
+
+               if(v->destructor_line > 0)
+                       out_addline_outfile(out);
+       } else {
+               out_printf(out, "#define VAR (%s->%s)\n", root, v->id);
+               out_printf(out, "\t{\n\t%s *self G_GNUC_UNUSED = %s;\n",
+                          typebase, self_id);
+               if(v->destructor_line > 0)
+                       out_addline_infile(out, v->destructor_line);
+
+               out_printf(out, "\t%s}\n", v->destructor);
+
+               if(v->destructor_line > 0)
+                       out_addline_outfile(out);
+               out_printf(out, "#undef VAR\n");
+       }
+
+       g_free(root);
+}
+
 /* put in code if it's needed */
 static void
 put_in_gen_code(Method *m)
 {
-       /* now we only have the freeing of the private structure */
-       if(privates>0 &&
-          m->method == OVERRIDE_METHOD &&
-          strcmp(m->id,"finalize")==0) {
-               out_printf(out,"\tg_free (%s (%s)->_priv);\n"
-                          "\t%s (%s)->_priv = NULL;\n",
-                          macrobase,
-                          ((FuncArg *)m->args->data)->name,
-                          macrobase,
-                          ((FuncArg *)m->args->data)->name);
+       if(m->method == OVERRIDE_METHOD &&
+          strcmp(m->id, "finalize")==0) {
+               if(privates > 0 || destructors > 0) {
+                       out_printf(out,"\t%s *___self = %s (%s);\n",
+                                  typebase, macrobase,
+                                  ((FuncArg *)m->args->data)->name);
+               }
+               if(destructors > 0) {
+                       GList *li;
+                       for(li = ((Class *)class)->nodes;
+                           li != NULL;
+                           li = li->next) {
+                               Node *n = li->data;
+                               if(n->type == VARIABLE_NODE)
+                                       print_destructor("___self",
+                                                        (Variable *)n);
+                       }
+               }
+               if(privates > 0) {
+                       out_printf(out,"\tg_free (___self->_priv);\n"
+                                  "\t___self->_priv = NULL;\n",
+                                  macrobase,
+                                  ((FuncArg *)m->args->data)->name,
+                                  macrobase,
+                                  ((FuncArg *)m->args->data)->name);
+               }
        }
 }
 
@@ -1213,13 +1356,13 @@ print_method_body(Method *m, int pre)
           ugly in the .c file, but that is not supposed to be
           human readable anyway. */
        if(m->cbuf) {
-               out_printf(out,"{\n");
+               out_printf(out, "{\n");
                if(m->ccode_line>0)
-                       out_addline_infile(out,m->ccode_line);
-               out_printf(out,"\t%s}",m->cbuf);
+                       out_addline_infile(out, m->ccode_line);
+               out_printf(out, "\t%s}", m->cbuf);
        }
 
-       out_printf(out,"}\n");
+       out_printf(out, "}\n");
 
        if(m->cbuf)
                out_addline_outfile(out);
@@ -1249,7 +1392,7 @@ get_arg_names_for_macro(Method *m)
 {
        char *p;
        GList *li;
-       GString *gs = g_string_new("");
+       GString *gs = g_string_new(NULL);
        p = "";
        for(li=m->args;li;li=g_list_next(li)) {
                FuncArg *arg = li->data;
@@ -1257,7 +1400,7 @@ get_arg_names_for_macro(Method *m)
                p = ",";
        }
        p = gs->str;
-       g_string_free(gs,FALSE);
+       g_string_free(gs, FALSE);
        return p;
 }
 
@@ -1284,7 +1427,7 @@ put_method(Method *m)
                else /* PUBLIC, PROTECTED */
                        print_method(out, "", "\n", "", " ", "\n",
                                     m, FALSE, FALSE);
-               print_method_body(m,TRUE);
+               print_method_body(m, TRUE);
                break;
        case SIGNAL_FIRST_METHOD:
        case SIGNAL_LAST_METHOD:
@@ -1480,9 +1623,9 @@ put_argument_nongnu_wrappers(Class *c)
                s = g_strdup(a->name);
                g_strup(s);
                if(a->atype)
-                       cast = get_type(a->atype,TRUE);
+                       cast = get_type(a->atype, TRUE);
                else
-                       cast = g_strdup(get_cast(a->gtktype,TRUE));
+                       cast = g_strdup(get_cast(a->gtktype, TRUE));
 
                if(cast) {
                        if(a->set)
@@ -1804,18 +1947,22 @@ print_class_block(Class *c)
 
        add_get_type();
 
-       if(no_gnu)
-               make_method_nongnu_aliases(c);
-       else {
-               out_printf(out,"\n#ifdef __GNUC__\n");
-               make_method_gnu_aliases(c);
-               out_printf(out,"#else /* __GNUC__ */\n");
-               make_method_nongnu_aliases(c);
-               out_printf(out,"#endif /* __GNUC__ */\n\n");
+       if(any_method_to_alias(c)) {
+               if(no_gnu)
+                       make_method_nongnu_aliases(c);
+               else {
+                       out_printf(out,"\n#ifdef __GNUC__\n");
+                       make_method_gnu_aliases(c);
+                       out_printf(out,"#else /* __GNUC__ */\n");
+                       make_method_nongnu_aliases(c);
+                       out_printf(out,"#endif /* __GNUC__ */\n\n");
+               }
        }
 
-       out_printf(out,"#define GET_NEW (gtk_type_new(%s_get_type()))\n",
-                  funcbase);
+       out_printf(out,"/* a macro for creating a new object of our type */\n");
+       out_printf(out,
+                  "#define GET_NEW ((%s *)gtk_type_new(%s_get_type()))\n\n",
+                  typebase, funcbase);
 
        add_inits(c);
 
@@ -1831,8 +1978,6 @@ print_class_block(Class *c)
                }
        }
 
-       out_printf(out,"#undef GET_NEW\n");
-
        add_bad_hack_to_avoid_unused_warnings(c);
 }
 
@@ -1852,13 +1997,14 @@ print_file_comments(void)
 {
        time_t curtime;
        time(&curtime);
-       out_printf(outh,"/* Generated by GOB (v%s)"
-              "   (do not edit directly) */\n\n",VERSION);
+       out_printf(outh, "/* Generated by GOB (v%s)"
+                  "   (do not edit directly) */\n\n", VERSION);
        if(outph)
                out_printf(outph,"/* Generated by GOB (v%s)"
-                          "   (do not edit directly) */\n\n",VERSION);
+                          "   (do not edit directly) */\n\n", VERSION);
        out_printf(out,"/* Generated by GOB (v%s) on %s"
-              "   (do not edit directly) */\n\n",VERSION,ctime(&curtime));
+                  "   (do not edit directly) */\n\n",
+                  VERSION, ctime(&curtime));
 }
 
 static void
@@ -1867,17 +2013,17 @@ print_includes(void)
        gboolean found_header;
        char *p;
 
-       p = g_strconcat(filebase,".h",NULL);
+       p = g_strconcat(filebase, ".h", NULL);
        found_header = TRUE;
-       if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) {
-               out_printf(out,"#include \"%s.h\"\n\n",filebase);
+       if(!g_list_find_custom(include_files, p, (GCompareFunc)strcmp)) {
+               out_printf(out, "#include \"%s.h\"\n\n", filebase);
                found_header = FALSE;
        }
        g_free(p);
 
        /* if we are creating a private header see if it was included */
        if(outph) {
-               p = g_strconcat(filebase,"-private.h",NULL);
+               p = g_strconcat(filebase, "-private.h", NULL);
                if(!g_list_find_custom(include_files,p,(GCompareFunc)strcmp)) {
                        out_printf(out,"#include \"%s-private.h\"\n\n",
                                   filebase);
@@ -1901,21 +2047,21 @@ print_header_prefixes(void)
 {
        char *p;
 
-       p = replace_sep(((Class *)class)->otype,'_');
+       p = replace_sep(((Class *)class)->otype, '_');
        g_strup(p);
-       out_printf(outh,"#ifndef __%s_H__\n#define __%s_H__\n\n",p,p);
+       out_printf(outh, "#ifndef __%s_H__\n#define __%s_H__\n\n", p, p);
        if(outph)
-               out_printf(outph,"#ifndef __%s_PRIVATE_H__\n"
+               out_printf(outph, "#ifndef __%s_PRIVATE_H__\n"
                           "#define __%s_PRIVATE_H__\n\n"
-                          "#include \"%s.h\"\n\n",p,p,filebase);
+                          "#include \"%s.h\"\n\n", p, p, filebase);
        g_free(p);
 
        if(!no_extern_c) {
-               out_printf(outh,"#ifdef __cplusplus\n"
+               out_printf(outh, "#ifdef __cplusplus\n"
                           "extern \"C\" {\n"
                           "#endif /* __cplusplus */\n\n");
                if(outph)
-                       out_printf(outph,"#ifdef __cplusplus\n"
+                       out_printf(outph, "#ifdef __cplusplus\n"
                                   "extern \"C\" {\n"
                                   "#endif /* __cplusplus */\n\n");
        }
@@ -2028,7 +2174,8 @@ print_help(void)
                "\t                        structure and protected "
                                          "prototypes inside c file\n"
                "\t--no-write,-n           Don't write output files, just "
-                                         "check syntax\n");
+                                         "check syntax\n"
+               "\t--no-lines              Don't print '#line' to output\n");
 }
 
 static void
@@ -2076,6 +2223,8 @@ parse_options(int argc, char *argv[])
                        no_extern_c = TRUE;
                } else if(strcmp(argv[i], "--no-write")==0) {
                        no_write = TRUE;
+               } else if(strcmp(argv[i], "--no-lines")==0) {
+                       no_lines = TRUE;
                } else if(strcmp(argv[i], "--")==0) {
                        /*further arguments are files*/
                        no_opts = TRUE;
@@ -2169,6 +2318,8 @@ main(int argc, char *argv[])
        overrides = count_overrides((Class *)class);
        privates = count_privates((Class *)class);
        protecteds = count_protecteds((Class *)class);
+       destructors = count_destructors((Class *)class);
+       initializers = count_initializers((Class *)class);
 
        make_bases();
        make_inits((Class *)class);
index b9f2c838d61222f48fb207166f3d0fe9004c8a22..05d20b3b5ca9190ba4f4f55186674e18b4e72f63 100644 (file)
@@ -10,6 +10,8 @@ extern gboolean got_error;
 extern gboolean always_private_header;
 extern gboolean no_private_header;
 extern gboolean no_extern_c;
+extern gboolean no_write;
+extern gboolean no_lines;
 
 extern char *filename;
 extern char *filebase;
index 77dabd1b752be2e049878612fa2bc3ae72afabbb..0803893528be99d0e6ac14a90b05a2b77fa0f11c 100644 (file)
--- a/src/out.c
+++ b/src/out.c
@@ -24,31 +24,34 @@ strchrcnt(char *s, char c)
 }
 
 void
-out_printf(FILE *fp,char *format,...)
+out_printf(FILE *fp, char *format,...)
 {
        va_list ap;
        char *s;
 
-       va_start(ap,format);
-       s = g_strdup_vprintf(format,ap);
+       va_start(ap, format);
+       s = g_strdup_vprintf(format, ap);
        va_end(ap);
 
        if(fp == out)
-               outline += strchrcnt(s,'\n');
+               outline += strchrcnt(s, '\n');
        else if(fp == outh)
-               outhline += strchrcnt(s,'\n');
+               outhline += strchrcnt(s, '\n');
        else if(fp == outph)
-               outphline += strchrcnt(s,'\n');
+               outphline += strchrcnt(s, '\n');
        else
                g_assert_not_reached();
 
-       fprintf(fp,"%s",s);
+       fprintf(fp, "%s", s);
        g_free(s);
 }
 
 void
 out_addline_infile(FILE *fp, int line)
 {
+       if(no_lines)
+               return;
+
        if(fp == out) {
                outline++;
                in_out = FALSE;
@@ -61,12 +64,15 @@ out_addline_infile(FILE *fp, int line)
        } else
                g_assert_not_reached();
 
-       fprintf(fp,"#line %d \"%s\"\n",line,filename);
+       fprintf(fp, "#line %d \"%s\"\n", line, filename);
 }
 
 void
 out_addline_outfile(FILE *fp)
 {
+       if(no_lines)
+               return;
+
        if(fp == out) {
                if(in_out) return;
                outline++;
index b70b55019420779aac7e0079e5bd948848c33f7f..4e7592d66eb1926b2a8d3bbc9edc1bca51a1e620 100644 (file)
@@ -65,6 +65,13 @@ static GList *checks = NULL;
 static int has_self = FALSE;
 static int vararg = FALSE;
 
+/* destructor and initializer for variables */
+static char *destructor = NULL;
+static int destructor_line = 0;
+static gboolean destructor_simple = TRUE;
+static char *initializer = NULL;
+static int initializer_line = 0;
+
 static GList *gtktypes = NULL;
 
 /* this can be a global as we will only do one function at a time
@@ -120,7 +127,10 @@ push_variable(char *name, int scope, int line_no, char *postfix)
 
        type->postfix = postfix;
        
-       var = new_variable(scope,type,name,line_no);
+       var = new_variable(scope, type, name, line_no,
+                          destructor, destructor_line,
+                          destructor_simple,
+                          initializer, initializer_line);
        class_nodes = g_list_append(class_nodes, var);
 }
 
@@ -220,8 +230,31 @@ push_self(char *id)
        funcargs = g_list_prepend(funcargs, node);
 }
 
+static Variable *
+find_var_or_die(const char *id, int line)
+{
+       GList *li;
+       char *s;
+
+       for(li = class_nodes; li != NULL; li = li->next) {
+               Variable *var;
+               Node *node = li->data;
+               if(node->type != VARIABLE_NODE)
+                       continue;
+               var = li->data;
+               if(strcmp(var->id, id)==0)
+                       return var;
+       }
+
+       s = g_strdup_printf(_("Variable %s not defined here"), id);
+       print_error(FALSE, s, line);
+
+       g_assert_not_reached();
+       return NULL;
+}
+
 
-#line 203 "parse.y"
+#line 236 "parse.y"
 typedef union {
        char *id;
        GString *cbuf;
@@ -243,26 +276,26 @@ typedef union {
 
 
 
-#define        YYFINAL         225
+#define        YYFINAL         239
 #define        YYFLAG          -32768
 #define        YYNTBASE        50
 
-#define YYTRANSLATE(x) ((unsigned)(x) <= 290 ? yytranslate[x] : 82)
+#define YYTRANSLATE(x) ((unsigned)(x) <= 290 ? yytranslate[x] : 86)
 
 static const char yytranslate[] = {     0,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,    48,     2,     2,     2,     2,     2,     2,    40,
-    41,    43,     2,    44,    49,     2,     2,     2,     2,     2,
-     2,     2,     2,     2,     2,     2,     2,     2,    39,    46,
-    47,    45,     2,     2,     2,     2,     2,     2,     2,     2,
+     2,     2,    48,     2,     2,     2,     2,     2,     2,    41,
+    42,    44,     2,    45,    49,     2,     2,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,    39,    47,
+    40,    46,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-     2,     2,    37,    42,    38,     2,     2,     2,     2,     2,
+     2,     2,    37,    43,    38,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -284,16 +317,17 @@ static const char yytranslate[] = {     0,
 #if YYDEBUG != 0
 static const short yyprhs[] = {     0,
      0,     4,     7,    10,    12,    14,    16,    18,    20,    22,
-    24,    27,    29,    34,    38,    43,    46,    49,    52,    54,
-    56,    58,    60,    62,    64,    69,    75,    87,    96,   102,
-   104,   108,   109,   113,   115,   117,   120,   122,   125,   128,
-   131,   133,   136,   139,   141,   143,   145,   147,   150,   152,
-   154,   157,   159,   162,   164,   166,   168,   170,   172,   175,
-   177,   180,   182,   186,   190,   193,   195,   200,   204,   206,
-   209,   211,   222,   234,   244,   254,   263,   275,   284,   290,
-   293,   297,   298,   300,   302,   306,   308,   312,   314,   318,
-   320,   323,   327,   334,   342,   345,   347,   349,   352,   355,
-   359,   363,   367,   371,   373,   376
+    24,    27,    29,    34,    38,    43,    46,    48,    50,    52,
+    54,    56,    58,    60,    62,    65,    69,    72,    76,    79,
+    82,    84,    86,    87,    93,   100,   112,   121,   127,   133,
+   135,   139,   140,   144,   146,   148,   151,   153,   156,   159,
+   162,   164,   167,   170,   172,   174,   176,   178,   181,   183,
+   185,   188,   190,   193,   195,   197,   199,   201,   203,   206,
+   208,   211,   213,   217,   221,   224,   226,   231,   235,   237,
+   240,   242,   253,   265,   275,   285,   294,   306,   315,   321,
+   324,   328,   329,   331,   333,   337,   339,   343,   345,   349,
+   351,   354,   358,   365,   373,   376,   378,   380,   383,   386,
+   390,   394,   398,   402,   404,   407
 };
 
 static const short yyrhs[] = {    52,
@@ -301,57 +335,61 @@ static const short yyrhs[] = {    52,
      0,    24,     0,    27,     0,    25,     0,    26,     0,    28,
      0,    29,     0,    52,    51,     0,    51,     0,    54,    37,
     55,    38,     0,    54,    37,    38,     0,     3,    22,     4,
-    22,     0,    55,    73,     0,    55,    57,     0,    55,    58,
-     0,    73,     0,    57,     0,    58,     0,    30,     0,    31,
-     0,    32,     0,    56,    62,    20,    39,     0,    56,    62,
-    20,    23,    39,     0,    33,    60,    59,    20,    20,    37,
-    24,    20,    37,    24,    39,     0,    33,    60,    59,    20,
-    20,    37,    24,    39,     0,    20,    40,    20,    62,    41,
-     0,    20,     0,    40,    61,    41,     0,     0,    20,    42,
-    61,     0,    20,     0,    63,     0,     5,    63,     0,    64,
-     0,    64,    67,     0,    12,    65,     0,    11,    65,     0,
-    65,     0,    12,    18,     0,    11,    18,     0,    18,     0,
-    17,     0,    16,     0,    20,     0,    66,    20,     0,    22,
-     0,     6,     0,    13,    15,     0,    13,     0,    14,    15,
-     0,    14,     0,    15,     0,     9,     0,     8,     0,     7,
-     0,    43,    67,     0,    43,     0,    20,    70,     0,    70,
-     0,    56,    20,    70,     0,    20,    56,    70,     0,    56,
-    70,     0,    68,     0,    20,    40,    71,    41,     0,    71,
-    44,    20,     0,    20,     0,    37,    24,     0,    39,     0,
-    35,    60,    69,    62,    20,    40,    75,    41,    74,    72,
-     0,    56,    35,    60,    68,    62,    20,    40,    75,    41,
-    74,    72,     0,    34,    56,    62,    20,    40,    75,    41,
-    74,    72,     0,    56,    34,    62,    20,    40,    75,    41,
-    74,    72,     0,    34,    62,    20,    40,    75,    41,    74,
-    72,     0,    36,    40,    22,    41,    62,    20,    40,    75,
-    41,    74,    72,     0,    56,    62,    20,    40,    75,    41,
-    74,    72,     0,    20,    40,    20,    41,    72,     0,    19,
-    81,     0,    19,    37,    24,     0,     0,     6,     0,    20,
-     0,    20,    44,    76,     0,    76,     0,    77,    44,    10,
-     0,    77,     0,    77,    44,    78,     0,    78,     0,    62,
-    20,     0,    62,    20,    23,     0,    62,    20,    40,    20,
-    79,    41,     0,    62,    20,    23,    40,    20,    79,    41,
-     0,    79,    80,     0,    80,     0,    20,     0,    45,    81,
-     0,    46,    81,     0,    45,    47,    81,     0,    46,    47,
-    81,     0,    47,    47,    81,     0,    48,    47,    81,     0,
-    21,     0,    49,    21,     0,    20,     0
+    22,     0,    55,    56,     0,    56,     0,    77,     0,    61,
+     0,    62,     0,    39,     0,    30,     0,    31,     0,    32,
+     0,    20,    20,     0,    20,    37,    24,     0,    40,    85,
+     0,    40,    37,    24,     0,    58,    59,     0,    59,    58,
+     0,    59,     0,    58,     0,     0,    57,    66,    20,    60,
+    39,     0,    57,    66,    20,    23,    60,    39,     0,    33,
+    64,    63,    20,    20,    37,    24,    20,    37,    24,    39,
+     0,    33,    64,    63,    20,    20,    37,    24,    39,     0,
+    33,    64,    63,    20,    20,     0,    20,    41,    20,    66,
+    42,     0,    20,     0,    41,    65,    42,     0,     0,    20,
+    43,    65,     0,    20,     0,    67,     0,     5,    67,     0,
+    68,     0,    68,    71,     0,    12,    69,     0,    11,    69,
+     0,    69,     0,    12,    18,     0,    11,    18,     0,    18,
+     0,    17,     0,    16,     0,    20,     0,    70,    20,     0,
+    22,     0,     6,     0,    13,    15,     0,    13,     0,    14,
+    15,     0,    14,     0,    15,     0,     9,     0,     8,     0,
+     7,     0,    44,    71,     0,    44,     0,    20,    74,     0,
+    74,     0,    57,    20,    74,     0,    20,    57,    74,     0,
+    57,    74,     0,    72,     0,    20,    41,    75,    42,     0,
+    75,    45,    20,     0,    20,     0,    37,    24,     0,    39,
+     0,    35,    64,    73,    66,    20,    41,    79,    42,    78,
+    76,     0,    57,    35,    64,    72,    66,    20,    41,    79,
+    42,    78,    76,     0,    34,    57,    66,    20,    41,    79,
+    42,    78,    76,     0,    57,    34,    66,    20,    41,    79,
+    42,    78,    76,     0,    34,    66,    20,    41,    79,    42,
+    78,    76,     0,    36,    41,    22,    42,    66,    20,    41,
+    79,    42,    78,    76,     0,    57,    66,    20,    41,    79,
+    42,    78,    76,     0,    20,    41,    20,    42,    76,     0,
+    19,    85,     0,    19,    37,    24,     0,     0,     6,     0,
+    20,     0,    20,    45,    80,     0,    80,     0,    81,    45,
+    10,     0,    81,     0,    81,    45,    82,     0,    82,     0,
+    66,    20,     0,    66,    20,    23,     0,    66,    20,    41,
+    20,    83,    42,     0,    66,    20,    23,    41,    20,    83,
+    42,     0,    83,    84,     0,    84,     0,    20,     0,    46,
+    85,     0,    47,    85,     0,    46,    40,    85,     0,    47,
+    40,    85,     0,    40,    40,    85,     0,    48,    40,    85,
+     0,    21,     0,    49,    21,     0,    20,     0
 };
 
 #endif
 
 #if YYDEBUG != 0
 static const short yyrline[] = { 0,
-   222,   223,   224,   225,   228,   234,   240,   246,   252,   258,
-   266,   267,   270,   275,   282,   287,   288,   289,   290,   291,
-   292,   295,   296,   297,   300,   303,   307,   342,   372,   381,
-   387,   388,   391,   394,   400,   401,   409,   413,   420,   423,
-   426,   429,   432,   435,   438,   441,   444,   447,   451,   454,
-   459,   462,   465,   468,   471,   476,   479,   482,   487,   488,
-   492,   504,   510,   522,   534,   537,   543,   548,   551,   556,
-   557,   561,   571,   581,   591,   601,   611,   617,   622,   643,
-   644,   648,   651,   652,   663,   673,   676,   677,   680,   681,
-   684,   687,   690,   698,   708,   709,   712,   725,   729,   733,
-   737,   741,   745,   751,   752,   756
+   255,   256,   257,   258,   261,   267,   273,   279,   285,   291,
+   299,   300,   303,   308,   315,   320,   321,   324,   325,   326,
+   327,   330,   331,   332,   335,   348,   364,   368,   376,   377,
+   378,   379,   380,   386,   389,   393,   428,   456,   521,   530,
+   536,   537,   540,   543,   549,   550,   558,   562,   569,   572,
+   575,   578,   581,   584,   587,   590,   593,   596,   600,   603,
+   608,   611,   614,   617,   620,   625,   628,   631,   636,   637,
+   641,   653,   659,   671,   683,   686,   692,   697,   700,   705,
+   706,   710,   720,   730,   740,   750,   760,   766,   771,   792,
+   793,   797,   800,   801,   812,   822,   825,   826,   829,   830,
+   833,   836,   839,   847,   857,   858,   861,   874,   878,   882,
+   886,   890,   894,   900,   901,   905
 };
 #endif
 
@@ -362,33 +400,36 @@ static const char * const yytname[] = {   "$","error","$undefined.","CLASS",
 "FROM","CONST","VOID","STRUCT","UNION","ENUM","THREEDOTS","SIGNED","UNSIGNED",
 "LONG","SHORT","INT","FLOAT","DOUBLE","CHAR","ONERROR","TOKEN","NUMBER","TYPETOKEN",
 "ARRAY_DIM","CCODE","HTCODE","PHCODE","HCODE","ACODE","ATCODE","PUBLIC","PRIVATE",
-"PROTECTED","ARGUMENT","VIRTUAL","SIGNAL","OVERRIDE","'{'","'}'","';'","'('",
-"')'","'|'","'*'","','","'>'","'<'","'='","'!'","'-'","prog","ccode","ccodes",
-"class","classdec","classcode","scope","variable","argument","argtype","flags",
-"flaglist","type","type1","type2","integer","tspecifier","stars","simplesigtype",
-"fullsigtype","sigtype","tokenlist","codenocode","method","onerror","funcargs",
-"arglist","arglist1","arg","checklist","check","numtok", NULL
+"PROTECTED","ARGUMENT","VIRTUAL","SIGNAL","OVERRIDE","'{'","'}'","';'","'='",
+"'('","')'","'|'","'*'","','","'>'","'<'","'!'","'-'","prog","ccode","ccodes",
+"class","classdec","classcode","thing","scope","destructor","initializer","varoptions",
+"variable","argument","argtype","flags","flaglist","type","type1","type2","integer",
+"tspecifier","stars","simplesigtype","fullsigtype","sigtype","tokenlist","codenocode",
+"method","onerror","funcargs","arglist","arglist1","arg","checklist","check",
+"numtok", NULL
 };
 #endif
 
 static const short yyr1[] = {     0,
     50,    50,    50,    50,    51,    51,    51,    51,    51,    51,
-    52,    52,    53,    53,    54,    55,    55,    55,    55,    55,
-    55,    56,    56,    56,    57,    57,    58,    58,    59,    59,
-    60,    60,    61,    61,    62,    62,    63,    63,    64,    64,
-    64,    64,    64,    64,    64,    64,    64,    64,    64,    64,
-    65,    65,    65,    65,    65,    66,    66,    66,    67,    67,
-    68,    68,    69,    69,    69,    69,    70,    71,    71,    72,
-    72,    73,    73,    73,    73,    73,    73,    73,    73,    74,
-    74,    74,    75,    75,    75,    75,    76,    76,    77,    77,
-    78,    78,    78,    78,    79,    79,    80,    80,    80,    80,
-    80,    80,    80,    81,    81,    81
+    52,    52,    53,    53,    54,    55,    55,    56,    56,    56,
+    56,    57,    57,    57,    58,    58,    59,    59,    60,    60,
+    60,    60,    60,    61,    61,    62,    62,    62,    63,    63,
+    64,    64,    65,    65,    66,    66,    67,    67,    68,    68,
+    68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
+    69,    69,    69,    69,    69,    70,    70,    70,    71,    71,
+    72,    72,    73,    73,    73,    73,    74,    75,    75,    76,
+    76,    77,    77,    77,    77,    77,    77,    77,    77,    78,
+    78,    78,    79,    79,    79,    79,    80,    80,    81,    81,
+    82,    82,    82,    82,    83,    83,    84,    84,    84,    84,
+    84,    84,    84,    85,    85,    85
 };
 
 static const short yyr2[] = {     0,
      3,     2,     2,     1,     1,     1,     1,     1,     1,     1,
-     2,     1,     4,     3,     4,     2,     2,     2,     1,     1,
-     1,     1,     1,     1,     4,     5,    11,     8,     5,     1,
+     2,     1,     4,     3,     4,     2,     1,     1,     1,     1,
+     1,     1,     1,     1,     2,     3,     2,     3,     2,     2,
+     1,     1,     0,     5,     6,    11,     8,     5,     5,     1,
      3,     0,     3,     1,     1,     2,     1,     2,     2,     2,
      1,     2,     2,     1,     1,     1,     1,     2,     1,     1,
      2,     1,     2,     1,     1,     1,     1,     1,     2,     1,
@@ -402,143 +443,149 @@ static const short yyr2[] = {     0,
 static const short yydefact[] = {     0,
      0,     5,     7,     8,     6,     9,    10,    12,     0,     4,
      0,     0,    11,     3,     2,     0,     0,     1,     0,    22,
-    23,    24,    32,     0,    32,     0,    14,     0,     0,    20,
-    21,    19,    15,     0,     0,     0,     0,    50,    58,    57,
-    56,     0,     0,    52,    54,    55,    46,    45,    44,    47,
-    49,     0,     0,    35,    37,    41,     0,     0,     0,    13,
-    17,    18,    16,     0,    32,     0,     0,    34,     0,    30,
-     0,    36,    43,    40,    42,    39,    51,    53,     0,     0,
-    60,    38,    48,     0,     0,    66,     0,    62,     0,     0,
-     0,     0,     0,     0,    31,     0,     0,     0,     0,    59,
-     0,     0,     0,    61,     0,    65,     0,     0,     0,     0,
-     0,     0,    25,     0,     0,    71,    79,    33,     0,     0,
-     0,    50,    47,     0,     0,    86,    88,    90,    69,     0,
-    64,    63,     0,     0,     0,     0,    26,     0,    70,     0,
-     0,     0,     0,    91,    82,     0,    67,     0,     0,     0,
-     0,     0,    82,    29,     0,    82,    85,    92,     0,     0,
-     0,    87,    89,    68,     0,     0,    82,     0,     0,     0,
-    28,     0,     0,     0,   106,   104,     0,     0,    80,    76,
-    82,     0,     0,     0,    78,     0,    74,     0,    97,     0,
-     0,     0,     0,     0,    96,    81,   105,     0,    82,    75,
-    82,     0,     0,     0,    98,     0,    99,     0,     0,    93,
-    95,    72,     0,     0,    27,    94,   100,   101,   102,   103,
-    77,    73,     0,     0,     0
+    23,    24,    42,     0,    42,     0,    14,    21,     0,    17,
+     0,    19,    20,    18,    15,     0,     0,     0,     0,    60,
+    68,    67,    66,     0,     0,    62,    64,    65,    56,    55,
+    54,    57,    59,     0,     0,    45,    47,    51,     0,     0,
+     0,    13,    16,     0,    42,     0,     0,    44,     0,    40,
+     0,    46,    53,    50,    52,    49,    61,    63,     0,     0,
+    70,    48,    58,     0,     0,    76,     0,    72,     0,     0,
+     0,    33,     0,     0,    41,     0,     0,     0,     0,    69,
+     0,     0,     0,    71,     0,    75,     0,     0,     0,     0,
+     0,     0,    33,     0,     0,    32,    31,     0,     0,    81,
+    89,    43,     0,    38,     0,    60,    57,     0,     0,    96,
+    98,   100,    79,     0,    74,    73,     0,     0,     0,     0,
+    25,     0,     0,   116,   114,     0,     0,    27,     0,    29,
+    30,    34,    80,     0,     0,     0,     0,   101,    92,     0,
+    77,     0,     0,     0,     0,     0,    26,    35,    28,   115,
+    92,    39,     0,    92,    95,   102,     0,     0,     0,    97,
+    99,    78,     0,     0,    92,     0,     0,     0,    37,     0,
+     0,     0,     0,    90,    86,    92,     0,     0,     0,    88,
+     0,    84,     0,   107,     0,     0,     0,     0,     0,   106,
+    91,     0,    92,    85,    92,     0,     0,     0,     0,   108,
+     0,   109,     0,   103,   105,    82,     0,     0,    36,   104,
+   112,   110,   111,   113,    87,    83,     0,     0,     0
 };
 
-static const short yydefgoto[] = {   223,
-     8,     9,    10,    11,    28,    29,    30,    31,    71,    36,
-    69,   124,    54,    55,    56,    57,    82,    86,    87,    88,
-   130,   117,    32,   161,   125,   126,   127,   128,   194,   195,
-   179
+static const short yydefgoto[] = {   237,
+     8,     9,    10,    11,    29,    30,    31,   116,   117,   118,
+    32,    33,    71,    38,    69,   128,    56,    57,    58,    59,
+    82,    86,    87,    88,   134,   121,    34,   179,   129,   130,
+   131,   132,   209,   210,   148
 };
 
-static const short yypact[] = {   136,
-     4,-32768,-32768,-32768,-32768,-32768,-32768,-32768,   136,   119,
-    32,    10,-32768,   119,   119,   146,    67,   119,    40,-32768,
--32768,-32768,    57,   120,    57,    68,-32768,   155,    59,-32768,
--32768,-32768,-32768,    78,    95,    96,   242,-32768,-32768,-32768,
--32768,   252,   258,   115,   126,-32768,-32768,-32768,-32768,-32768,
--32768,   207,   129,-32768,   113,-32768,   137,    70,   151,-32768,
--32768,-32768,-32768,   207,    57,   138,   133,   141,   167,   152,
-   190,-32768,-32768,-32768,-32768,-32768,-32768,-32768,   197,   186,
-   113,-32768,-32768,     2,   208,-32768,   207,-32768,   194,   224,
-   226,   -19,   131,    95,-32768,   232,   241,   223,   225,-32768,
-   228,   249,   254,-32768,    -4,-32768,   255,   207,   237,    -4,
-   207,   239,-32768,   225,   256,-32768,-32768,-32768,   207,   244,
-   225,   238,    47,   262,   243,-32768,   245,-32768,-32768,    66,
--32768,-32768,   246,   263,   225,   265,-32768,   247,-32768,   250,
-   266,   251,   207,     7,   268,   189,-32768,   273,   225,   257,
-   253,   259,   268,-32768,    -1,   268,-32768,   260,   275,   -10,
-   131,-32768,-32768,-32768,   261,   225,   268,   225,   131,   264,
--32768,   131,   276,    76,-32768,-32768,   274,   282,-32768,-32768,
-   268,   267,   131,   269,-32768,   280,-32768,    76,-32768,    62,
-    65,   270,   271,    58,-32768,-32768,-32768,   131,   268,-32768,
-   268,   272,    72,    -8,-32768,    -8,-32768,    -8,    -8,-32768,
--32768,-32768,   131,   131,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,   305,   306,-32768
+static const short yypact[] = {    54,
+   -16,-32768,-32768,-32768,-32768,-32768,-32768,-32768,    54,   156,
+   -19,    38,-32768,   156,   156,   140,    29,   156,    25,-32768,
+-32768,-32768,    35,   137,    35,    47,-32768,-32768,   157,-32768,
+    89,-32768,-32768,-32768,-32768,   102,   127,   142,   245,-32768,
+-32768,-32768,-32768,   261,   267,   150,   151,-32768,-32768,-32768,
+-32768,-32768,-32768,   210,   166,-32768,   167,-32768,   174,    95,
+   191,-32768,-32768,   210,    35,   200,   187,   188,   196,   206,
+   229,-32768,-32768,-32768,-32768,-32768,-32768,-32768,   235,   225,
+   167,-32768,-32768,   -10,   248,-32768,   210,-32768,   227,   251,
+   252,    45,    92,   127,-32768,   257,   258,   242,   228,-32768,
+   243,   266,   268,-32768,   -17,-32768,   269,   210,   246,   -17,
+   210,    34,   -11,     6,   228,   250,   271,   253,   270,-32768,
+-32768,-32768,   210,   256,   228,   254,    -1,   275,   259,-32768,
+   260,-32768,-32768,   119,-32768,-32768,   262,   277,   228,   278,
+-32768,   276,   263,-32768,-32768,   280,   285,-32768,   265,-32768,
+-32768,-32768,-32768,   272,   284,   273,   210,    91,   290,   192,
+-32768,   279,   228,   281,   274,   282,-32768,-32768,-32768,-32768,
+   290,-32768,    -7,   290,-32768,   283,   291,    40,    92,-32768,
+-32768,-32768,   286,   228,   290,   228,    92,   288,-32768,    92,
+   292,    93,   289,-32768,-32768,   290,   287,    92,   293,-32768,
+   294,-32768,    93,-32768,   296,    70,    72,   297,    27,-32768,
+-32768,    92,   290,-32768,   290,   295,    88,    15,    15,-32768,
+    15,-32768,    15,-32768,-32768,-32768,    92,    92,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,   310,   317,-32768
 };
 
 static const short yypgoto[] = {-32768,
-    37,   145,   298,-32768,-32768,   -23,   281,   284,-32768,   -17,
-   219,   -24,   277,-32768,    15,-32768,   234,   229,-32768,   -60,
--32768,  -154,   288,  -150,  -112,   176,-32768,   175,   134,  -141,
-   -37
+   255,   106,   311,-32768,-32768,   298,   -22,   202,   205,   213,
+-32768,-32768,-32768,    -6,   236,   -24,   299,-32768,    73,-32768,
+   264,   240,-32768,    53,-32768,  -175,-32768,  -157,  -114,   175,
+-32768,   173,   136,  -201,  -173
 };
 
 
-#define        YYLAST          322
-
-
-static const short yytable[] = {    53,
-    52,   138,   169,   112,    66,   172,   180,    58,   142,   175,
-   176,   175,   176,    17,   185,   101,   183,   187,   170,   113,
-   114,   101,   151,   104,   106,    12,   177,    79,   200,   158,
-   198,    20,    21,    22,    85,   102,   165,   171,   178,    90,
-   178,   102,   131,   212,   132,    13,   159,    91,   213,   104,
-   214,    13,   211,   182,    13,   184,    74,    76,   221,   222,
-   103,   211,   107,    37,    38,    39,    40,    41,    16,    42,
-    43,    44,    45,    46,    47,    48,    49,   189,    50,    34,
-    51,   175,   176,   134,   175,   176,   136,   -84,    33,    84,
-   143,   189,    64,    65,   140,   189,    35,    67,   210,    20,
-    21,    22,   190,   191,   192,   193,   147,    59,   204,   148,
-   178,   206,   216,   178,    68,    70,   190,   191,   192,   193,
-   190,   191,   192,   193,    37,    38,    39,    40,    41,    77,
-    42,    43,    44,    45,    46,    47,    48,    49,     1,    50,
-    78,    51,     2,     3,     4,     5,     6,     7,    80,    20,
-    21,    22,   205,   207,    15,    81,    83,    92,    18,     2,
-     3,     4,     5,     6,     7,    19,   217,   115,   218,   116,
-   219,   220,    89,    93,    19,    20,    21,    22,    23,    24,
-    25,    26,    94,    27,    20,    21,    22,    23,    24,    25,
-    26,    96,    60,    37,    38,    39,    40,    41,   162,    42,
-    43,    44,    45,    46,    47,    48,    49,    95,    50,    97,
-    51,    37,    38,    39,    40,    41,    98,    42,    43,    44,
-    45,    46,    47,    48,    49,    99,    50,   105,    51,    37,
-   122,    39,    40,    41,   108,    42,    43,    44,    45,    46,
-    47,    48,    49,   109,   123,   110,    51,    38,    39,    40,
-    41,   119,    42,    43,    44,    45,    46,    47,    48,    49,
-   120,    50,   121,    51,    44,    45,    46,   102,   129,    73,
-    44,    45,    46,   101,   133,    75,   135,   137,   -83,   139,
-   141,   144,   150,   145,   152,   149,   160,   153,   146,   155,
-   154,   156,   164,   167,   174,   188,   166,   196,   168,   173,
-   186,   181,   197,   202,   224,   225,    14,   199,    61,   201,
-   215,    62,   118,    72,   100,    63,   208,   209,   157,   111,
-   163,   203
+#define        YYLAST          345
+
+
+static const short yytable[] = {    55,
+   149,    54,   101,   195,   194,    12,    66,   225,   112,   101,
+   156,   200,   188,   187,   202,   225,   190,    16,    60,    20,
+    21,    22,   214,   102,   165,   144,   145,   198,   114,    79,
+   102,   189,   220,   222,   144,   145,   226,    85,   212,    90,
+   -94,    17,   146,   157,   231,   232,   204,   233,   183,   234,
+    35,   235,   236,   141,   147,   227,     1,   228,    91,   144,
+   145,   103,   107,   147,   112,    36,   205,   113,   224,   197,
+   142,   199,   206,   207,   208,    37,   193,     2,     3,     4,
+     5,     6,     7,   138,   114,   115,   140,    61,   147,   144,
+   145,   144,   145,    39,    40,    41,    42,    43,   154,    44,
+    45,    46,    47,    48,    49,    50,    51,   204,    52,   219,
+    53,   221,   204,   176,    84,    15,    74,    76,   147,    18,
+   147,    67,    64,    65,    20,    21,    22,   205,   119,   230,
+   120,   177,   205,   206,   207,   208,   104,   106,   206,   207,
+   208,    39,    40,    41,    42,    43,    68,    44,    45,    46,
+    47,    48,    49,    50,    51,   135,    52,   136,    53,    19,
+   161,    70,   104,   162,    77,    78,    20,    21,    22,    20,
+    21,    22,    23,    24,    25,    26,    19,    27,    28,     2,
+     3,     4,     5,     6,     7,    80,    20,    21,    22,    23,
+    24,    25,    26,    83,    62,    28,    39,    40,    41,    42,
+    43,   180,    44,    45,    46,    47,    48,    49,    50,    51,
+    81,    52,    89,    53,    39,    40,    41,    42,    43,    92,
+    44,    45,    46,    47,    48,    49,    50,    51,    93,    52,
+    94,    53,    39,   126,    41,    42,    43,    95,    44,    45,
+    46,    47,    48,    49,    50,    51,    96,   127,    97,    53,
+    40,    41,    42,    43,    98,    44,    45,    46,    47,    48,
+    49,    50,    51,    13,    52,    99,    53,   105,   108,    13,
+   109,   110,    13,    46,    47,    48,   123,   124,    73,    46,
+    47,    48,   125,   102,    75,   133,   139,   101,   137,   114,
+   112,   152,   155,   153,   158,   -93,   164,   166,   182,   167,
+   159,   168,   163,   169,   160,   170,   171,   173,   178,   238,
+   192,   203,   211,   172,   174,   185,   239,   216,   151,    14,
+   150,   184,   186,   191,   201,   143,    63,   196,   213,   122,
+   111,   175,   181,   229,   215,   218,   223,    72,   217,     0,
+     0,     0,     0,     0,   100
 };
 
 static const short yycheck[] = {    24,
-    24,   114,   153,    23,    29,   156,   161,    25,   121,    20,
-    21,    20,    21,     4,   169,    20,   167,   172,    20,    39,
-    40,    20,   135,    84,    85,    22,    37,    52,   183,    23,
-   181,    30,    31,    32,    58,    40,   149,    39,    49,    64,
-    49,    40,   103,   198,   105,     9,    40,    65,   199,   110,
-   201,    15,   194,   166,    18,   168,    42,    43,   213,   214,
-    84,   203,    87,     5,     6,     7,     8,     9,    37,    11,
+   115,    24,    20,   179,   178,    22,    31,   209,    20,    20,
+   125,   187,    20,   171,   190,   217,   174,    37,    25,    30,
+    31,    32,   198,    41,   139,    20,    21,   185,    40,    54,
+    41,    39,   206,   207,    20,    21,   212,    60,   196,    64,
+    42,     4,    37,    45,   218,   219,    20,   221,   163,   223,
+    22,   227,   228,    20,    49,   213,     3,   215,    65,    20,
+    21,    84,    87,    49,    20,    41,    40,    23,    42,   184,
+    37,   186,    46,    47,    48,    41,    37,    24,    25,    26,
+    27,    28,    29,   108,    40,    41,   111,    41,    49,    20,
+    21,    20,    21,     5,     6,     7,     8,     9,   123,    11,
     12,    13,    14,    15,    16,    17,    18,    20,    20,    40,
-    22,    20,    21,   108,    20,    21,   111,    41,    22,    20,
-    44,    20,    34,    35,   119,    20,    40,    20,    41,    30,
-    31,    32,    45,    46,    47,    48,    41,    40,    47,    44,
-    49,    47,    41,    49,    20,    20,    45,    46,    47,    48,
-    45,    46,    47,    48,     5,     6,     7,     8,     9,    15,
-    11,    12,    13,    14,    15,    16,    17,    18,     3,    20,
-    15,    22,    24,    25,    26,    27,    28,    29,    20,    30,
-    31,    32,   190,   191,    10,    43,    20,    20,    14,    24,
-    25,    26,    27,    28,    29,    20,   204,    37,   206,    39,
-   208,   209,    22,    41,    20,    30,    31,    32,    33,    34,
-    35,    36,    42,    38,    30,    31,    32,    33,    34,    35,
-    36,    40,    38,     5,     6,     7,     8,     9,    10,    11,
-    12,    13,    14,    15,    16,    17,    18,    41,    20,    20,
-    22,     5,     6,     7,     8,     9,    20,    11,    12,    13,
-    14,    15,    16,    17,    18,    40,    20,    20,    22,     5,
-     6,     7,     8,     9,    41,    11,    12,    13,    14,    15,
-    16,    17,    18,    20,    20,    20,    22,     6,     7,     8,
-     9,    20,    11,    12,    13,    14,    15,    16,    17,    18,
-    20,    20,    40,    22,    13,    14,    15,    40,    20,    18,
-    13,    14,    15,    20,    20,    18,    40,    39,    41,    24,
-    37,    20,    20,    41,    20,    40,    19,    41,    44,    24,
-    41,    41,    20,    41,    20,    20,    40,    24,    40,    40,
-    37,    41,    21,    24,     0,     0,     9,    41,    28,    41,
-    39,    28,    94,    37,    81,    28,    47,    47,   143,    91,
-   146,   188
+    22,    40,    20,    23,    20,    10,    44,    45,    49,    14,
+    49,    20,    34,    35,    30,    31,    32,    40,    37,    42,
+    39,    41,    40,    46,    47,    48,    84,    85,    46,    47,
+    48,     5,     6,     7,     8,     9,    20,    11,    12,    13,
+    14,    15,    16,    17,    18,   103,    20,   105,    22,    20,
+    42,    20,   110,    45,    15,    15,    30,    31,    32,    30,
+    31,    32,    33,    34,    35,    36,    20,    38,    39,    24,
+    25,    26,    27,    28,    29,    20,    30,    31,    32,    33,
+    34,    35,    36,    20,    38,    39,     5,     6,     7,     8,
+     9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+    44,    20,    22,    22,     5,     6,     7,     8,     9,    20,
+    11,    12,    13,    14,    15,    16,    17,    18,    42,    20,
+    43,    22,     5,     6,     7,     8,     9,    42,    11,    12,
+    13,    14,    15,    16,    17,    18,    41,    20,    20,    22,
+     6,     7,     8,     9,    20,    11,    12,    13,    14,    15,
+    16,    17,    18,     9,    20,    41,    22,    20,    42,    15,
+    20,    20,    18,    13,    14,    15,    20,    20,    18,    13,
+    14,    15,    41,    41,    18,    20,    41,    20,    20,    40,
+    20,    39,    37,    24,    20,    42,    20,    20,    20,    24,
+    42,    39,    41,    24,    45,    21,    42,    24,    19,     0,
+    20,    20,    24,    42,    42,    42,     0,    24,   117,     9,
+   116,    41,    41,    41,    37,   113,    29,    42,    42,    94,
+    91,   157,   160,    39,    42,    40,    40,    39,   203,    -1,
+    -1,    -1,    -1,    -1,    81
 };
 /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
 #line 3 "/usr/lib/bison.simple"
@@ -1084,23 +1131,23 @@ yyreduce:
   switch (yyn) {
 
 case 1:
-#line 222 "parse.y"
+#line 255 "parse.y"
 { ; ;
     break;}
 case 2:
-#line 223 "parse.y"
+#line 256 "parse.y"
 { ; ;
     break;}
 case 3:
-#line 224 "parse.y"
+#line 257 "parse.y"
 { ; ;
     break;}
 case 4:
-#line 225 "parse.y"
+#line 258 "parse.y"
 { ; ;
     break;}
 case 5:
-#line 228 "parse.y"
+#line 261 "parse.y"
 {
                        Node *node = new_ccode(C_CCODE,(yyvsp[0].cbuf)->str,
                                               ccode_line);
@@ -1109,7 +1156,7 @@ case 5:
                                        ;
     break;}
 case 6:
-#line 234 "parse.y"
+#line 267 "parse.y"
 {
                        Node *node = new_ccode(H_CCODE,(yyvsp[0].cbuf)->str,
                                               ccode_line);
@@ -1118,7 +1165,7 @@ case 6:
                                        ;
     break;}
 case 7:
-#line 240 "parse.y"
+#line 273 "parse.y"
 {
                        Node *node = new_ccode(HT_CCODE,(yyvsp[0].cbuf)->str,
                                               ccode_line);
@@ -1127,7 +1174,7 @@ case 7:
                                        ;
     break;}
 case 8:
-#line 246 "parse.y"
+#line 279 "parse.y"
 {
                        Node *node = new_ccode(PH_CCODE,(yyvsp[0].cbuf)->str,
                                               ccode_line);
@@ -1136,7 +1183,7 @@ case 8:
                                        ;
     break;}
 case 9:
-#line 252 "parse.y"
+#line 285 "parse.y"
 {
                        Node *node = new_ccode(A_CCODE,(yyvsp[0].cbuf)->str,
                                               ccode_line);
@@ -1145,7 +1192,7 @@ case 9:
                                        ;
     break;}
 case 10:
-#line 258 "parse.y"
+#line 291 "parse.y"
 {
                        Node *node = new_ccode(AT_CCODE,(yyvsp[0].cbuf)->str,
                                               ccode_line);
@@ -1154,15 +1201,15 @@ case 10:
                                        ;
     break;}
 case 11:
-#line 266 "parse.y"
+#line 299 "parse.y"
 { ; ;
     break;}
 case 12:
-#line 267 "parse.y"
+#line 300 "parse.y"
 { ; ;
     break;}
 case 13:
-#line 270 "parse.y"
+#line 303 "parse.y"
 {
                        ((Class *)class)->nodes = class_nodes;
                        class_nodes = NULL;
@@ -1170,7 +1217,7 @@ case 13:
                                                ;
     break;}
 case 14:
-#line 275 "parse.y"
+#line 308 "parse.y"
 {
                        ((Class *)class)->nodes = NULL;
                        class_nodes = NULL;
@@ -1178,61 +1225,132 @@ case 14:
                                                ;
     break;}
 case 15:
-#line 282 "parse.y"
+#line 315 "parse.y"
 {
                        class = new_class(yyvsp[-2].id,yyvsp[0].id,NULL);
                                                ;
     break;}
 case 16:
-#line 287 "parse.y"
+#line 320 "parse.y"
 { ; ;
     break;}
 case 17:
-#line 288 "parse.y"
+#line 321 "parse.y"
 { ; ;
     break;}
 case 18:
-#line 289 "parse.y"
+#line 324 "parse.y"
 { ; ;
     break;}
 case 19:
-#line 290 "parse.y"
+#line 325 "parse.y"
 { ; ;
     break;}
 case 20:
-#line 291 "parse.y"
+#line 326 "parse.y"
 { ; ;
     break;}
 case 21:
-#line 292 "parse.y"
+#line 327 "parse.y"
 { ; ;
     break;}
 case 22:
-#line 295 "parse.y"
+#line 330 "parse.y"
 { the_scope = PUBLIC_SCOPE; ;
     break;}
 case 23:
-#line 296 "parse.y"
+#line 331 "parse.y"
 { the_scope = PRIVATE_SCOPE; ;
     break;}
 case 24:
-#line 297 "parse.y"
+#line 332 "parse.y"
 { the_scope = PROTECTED_SCOPE; ;
     break;}
 case 25:
-#line 300 "parse.y"
+#line 335 "parse.y"
 {
-                       push_variable(yyvsp[-1].id,the_scope,yyvsp[-3].line,NULL);
-                                               ;
+                       if(strcmp(yyvsp[-1].id, "destroywith")==0) {
+                               g_free(yyvsp[-1].id);
+                               destructor = yyvsp[0].id;
+                               destructor_line = ccode_line;
+                               destructor_simple = TRUE;
+                       } else {
+                               g_free(yyvsp[-1].id);
+                               g_free(yyvsp[0].id);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                               ;
     break;}
 case 26:
-#line 303 "parse.y"
+#line 348 "parse.y"
 {
-                       push_variable(yyvsp[-2].id,the_scope,yyvsp[-4].line,yyvsp[-1].id);
-                                               ;
+                       if(strcmp(yyvsp[-2].id, "destroy")==0) {
+                               g_free(yyvsp[-2].id);
+                               destructor = (yyvsp[0].cbuf)->str;
+                               g_string_free(yyvsp[0].cbuf, FALSE);
+                               destructor_line = ccode_line;
+                               destructor_simple = FALSE;
+                       } else {
+                               g_free(yyvsp[-2].id);
+                               g_string_free(yyvsp[0].cbuf, TRUE);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                                       ;
     break;}
 case 27:
-#line 307 "parse.y"
+#line 364 "parse.y"
+{
+                       initializer = yyvsp[0].id;
+                       initializer_line = ccode_line;
+                               ;
+    break;}
+case 28:
+#line 368 "parse.y"
+{
+                       initializer = (yyvsp[0].cbuf)->str;
+                       initializer_line = ccode_line;
+                       g_string_free(yyvsp[0].cbuf, FALSE);
+                               ;
+    break;}
+case 29:
+#line 376 "parse.y"
+{ ; ;
+    break;}
+case 30:
+#line 377 "parse.y"
+{ ; ;
+    break;}
+case 31:
+#line 378 "parse.y"
+{ destructor = NULL; ;
+    break;}
+case 32:
+#line 379 "parse.y"
+{ initializer = NULL; ;
+    break;}
+case 33:
+#line 380 "parse.y"
+{
+                       destructor = NULL;
+                       initializer = NULL;
+                                       ;
+    break;}
+case 34:
+#line 386 "parse.y"
+{
+                       push_variable(yyvsp[-2].id, the_scope,yyvsp[-4].line, NULL);
+                                               ;
+    break;}
+case 35:
+#line 389 "parse.y"
+{
+                       push_variable(yyvsp[-3].id, the_scope, yyvsp[-5].line, yyvsp[-2].id);
+                                               ;
+    break;}
+case 36:
+#line 393 "parse.y"
 {
                        if(strcmp(yyvsp[-6].id,"get")==0 &&
                           strcmp(yyvsp[-3].id,"set")==0) {
@@ -1269,8 +1387,8 @@ case 27:
                        }
                                                ;
     break;}
-case 28:
-#line 342 "parse.y"
+case 37:
+#line 428 "parse.y"
 {
                        if(strcmp(yyvsp[-3].id,"get")==0) {
                                Node *node;
@@ -1300,8 +1418,74 @@ case 28:
                        }
                                                ;
     break;}
-case 29:
-#line 372 "parse.y"
+case 38:
+#line 456 "parse.y"
+{
+                       Node *node;
+                       char *get, *set;
+                       Variable *var;
+                       Type *type;
+                       char *root;
+                       
+                       if(strcmp(yyvsp[0].id,"link")!=0 &&
+                          strcmp(yyvsp[0].id,"stringlink")!=0 &&
+                          strcmp(yyvsp[0].id,"objectlink")!=0) {
+                               g_free(yyvsp[0].id); g_free(yyvsp[-2].id);
+                               g_free(yyvsp[-1].id);
+                               g_list_foreach(yyvsp[-3].list,(GFunc)g_free,NULL);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+
+                       type = pop_type();
+
+                       var = find_var_or_die(yyvsp[-1].id, yyvsp[-4].line);
+                       if(var->scope == PRIVATE_SCOPE)
+                               root = "self->_priv";
+                       else
+                               root = "self";
+
+                       if(strcmp(yyvsp[0].id,"link")==0) {
+                               set = g_strdup_printf("%s->%s = ARG;",
+                                                     root, yyvsp[-1].id);
+                       } else if(strcmp(yyvsp[0].id,"stringlink")==0) {
+                               set = g_strdup_printf("g_free(%s->%s); "
+                                                     "%s->%s = g_strdup(ARG);",
+                                                     root, yyvsp[-1].id,
+                                                     root, yyvsp[-1].id);
+                       } else if(strcmp(yyvsp[0].id,"objectlink")==0) {
+                               set = g_strdup_printf(
+                                 "if(%s->%s) "
+                                  "gtk_object_unref(GTK_OBJECT(%s->%s)); "
+                                 "%s->%s = ARG; "
+                                 "if(%s->%s) "
+                                  "gtk_object_ref(GTK_OBJECT(%s->%s)); ",
+                                 root, yyvsp[-1].id,
+                                 root, yyvsp[-1].id,
+                                 root, yyvsp[-1].id,
+                                 root, yyvsp[-1].id,
+                                 root, yyvsp[-1].id);
+                       } else {
+                               g_assert_not_reached();
+                       }
+
+                       /* get is the same for everything */
+                       get = g_strdup_printf("ARG = %s->%s;", root, yyvsp[-1].id);
+
+                       g_free(yyvsp[0].id);
+
+
+                       if(!type)
+                               type = copy_type(var->vtype);
+
+                       node = new_argument(yyvsp[-2].id, type, yyvsp[-3].list,
+                                           yyvsp[-1].id, get, yyvsp[-4].line,
+                                           set, yyvsp[-4].line, yyvsp[-4].line);
+                       class_nodes = g_list_append(class_nodes,node);
+                                               ;
+    break;}
+case 39:
+#line 521 "parse.y"
 {
                        if(strcmp(yyvsp[-2].id,"type")!=0) {
                                g_free(yyvsp[-4].id);
@@ -1312,39 +1496,39 @@ case 29:
                        yyval.id = yyvsp[-4].id;
                                                ;
     break;}
-case 30:
-#line 381 "parse.y"
+case 40:
+#line 530 "parse.y"
 {
                        yyval.id = yyvsp[0].id;
                        typestack = g_list_prepend(typestack,NULL);
                                                ;
     break;}
-case 31:
-#line 387 "parse.y"
+case 41:
+#line 536 "parse.y"
 { yyval.list = yyvsp[-1].list; ;
     break;}
-case 32:
-#line 388 "parse.y"
+case 42:
+#line 537 "parse.y"
 { yyval.list = NULL; ;
     break;}
-case 33:
-#line 391 "parse.y"
+case 43:
+#line 540 "parse.y"
 {
                        yyval.list = g_list_append(yyvsp[0].list,yyvsp[-2].id);
                                                ;
     break;}
-case 34:
-#line 394 "parse.y"
+case 44:
+#line 543 "parse.y"
 {
                        yyval.list = g_list_append(NULL,yyvsp[0].id);
                                                ;
     break;}
-case 35:
-#line 400 "parse.y"
+case 45:
+#line 549 "parse.y"
 { ; ;
     break;}
-case 36:
-#line 401 "parse.y"
+case 46:
+#line 550 "parse.y"
 {
                        Type *type = typestack->data;
                        char *oldname = type->name;
@@ -1352,152 +1536,152 @@ case 36:
                        g_free(oldname);
                                                ;
     break;}
-case 37:
-#line 409 "parse.y"
+case 47:
+#line 558 "parse.y"
 {
                        Node *node = new_type(0,yyvsp[0].id,NULL);
                        typestack = g_list_prepend(typestack,node);
                                                ;
     break;}
-case 38:
-#line 413 "parse.y"
+case 48:
+#line 562 "parse.y"
 {
                        Node *node = new_type(stars,yyvsp[-1].id,NULL);
                        stars = 0;
                        typestack = g_list_prepend(typestack,node);
                                                ;
     break;}
-case 39:
-#line 420 "parse.y"
+case 49:
+#line 569 "parse.y"
 {
                        yyval.id = g_strconcat("unsigned ",yyvsp[0].id,NULL);
                                                ;
     break;}
-case 40:
-#line 423 "parse.y"
+case 50:
+#line 572 "parse.y"
 {
                        yyval.id = g_strconcat("signed ",yyvsp[0].id,NULL);
                                                ;
     break;}
-case 41:
-#line 426 "parse.y"
+case 51:
+#line 575 "parse.y"
 {
                        yyval.id = g_strdup(yyvsp[0].id);
                                                ;
     break;}
-case 42:
-#line 429 "parse.y"
+case 52:
+#line 578 "parse.y"
 {
                        yyval.id = g_strdup("unsigned char");
                                                ;
     break;}
-case 43:
-#line 432 "parse.y"
+case 53:
+#line 581 "parse.y"
 {
                        yyval.id = g_strdup("signed char");
                                                ;
     break;}
-case 44:
-#line 435 "parse.y"
+case 54:
+#line 584 "parse.y"
 {
                        yyval.id = g_strdup("char");
                                                ;
     break;}
-case 45:
-#line 438 "parse.y"
+case 55:
+#line 587 "parse.y"
 {
                        yyval.id = g_strdup("double");
                                                ;
     break;}
-case 46:
-#line 441 "parse.y"
+case 56:
+#line 590 "parse.y"
 {
                        yyval.id = g_strdup("float");
                                                ;
     break;}
-case 47:
-#line 444 "parse.y"
+case 57:
+#line 593 "parse.y"
 {
                        yyval.id = yyvsp[0].id;
                                                ;
     break;}
-case 48:
-#line 447 "parse.y"
+case 58:
+#line 596 "parse.y"
 {
                        yyval.id = g_strconcat(yyvsp[-1].id,yyvsp[0].id,NULL);
                        g_free(yyvsp[0].id);
                                                ;
     break;}
-case 49:
-#line 451 "parse.y"
+case 59:
+#line 600 "parse.y"
 {
                        yyval.id = yyvsp[0].id;
                                                ;
     break;}
-case 50:
-#line 454 "parse.y"
+case 60:
+#line 603 "parse.y"
 {
                        yyval.id = g_strdup("void");
                                                ;
     break;}
-case 51:
-#line 459 "parse.y"
+case 61:
+#line 608 "parse.y"
 {
                        yyval.id = "long int";
                                                ;
     break;}
-case 52:
-#line 462 "parse.y"
+case 62:
+#line 611 "parse.y"
 {
                        yyval.id = "long";
                                                ;
     break;}
-case 53:
-#line 465 "parse.y"
+case 63:
+#line 614 "parse.y"
 {
                        yyval.id = "short int";
                                                ;
     break;}
-case 54:
-#line 468 "parse.y"
+case 64:
+#line 617 "parse.y"
 {
                        yyval.id = "short";
                                                ;
     break;}
-case 55:
-#line 471 "parse.y"
+case 65:
+#line 620 "parse.y"
 {
                        yyval.id = "int";
                                                ;
     break;}
-case 56:
-#line 476 "parse.y"
+case 66:
+#line 625 "parse.y"
 {
                        yyval.id = "enum ";
                                                ;
     break;}
-case 57:
-#line 479 "parse.y"
+case 67:
+#line 628 "parse.y"
 {
                        yyval.id = "union ";
                                                ;
     break;}
-case 58:
-#line 482 "parse.y"
+case 68:
+#line 631 "parse.y"
 {
                        yyval.id = "struct ";
                                                ;
     break;}
-case 59:
-#line 487 "parse.y"
+case 69:
+#line 636 "parse.y"
 { stars++; ;
     break;}
-case 60:
-#line 488 "parse.y"
+case 70:
+#line 637 "parse.y"
 { stars++; ;
     break;}
-case 61:
-#line 492 "parse.y"
+case 71:
+#line 641 "parse.y"
 {
                        if(strcmp(yyvsp[-1].id,"first")==0)
                                yyval.sigtype = SIGNAL_FIRST_METHOD;
@@ -1511,14 +1695,14 @@ case 61:
                        g_free(yyvsp[-1].id);
                                        ;
     break;}
-case 62:
-#line 504 "parse.y"
+case 72:
+#line 653 "parse.y"
 {
                        yyval.sigtype = SIGNAL_LAST_METHOD;
                                        ;
     break;}
-case 63:
-#line 510 "parse.y"
+case 73:
+#line 659 "parse.y"
 {
                        if(strcmp(yyvsp[-1].id,"first")==0)
                                yyval.sigtype = SIGNAL_FIRST_METHOD;
@@ -1532,8 +1716,8 @@ case 63:
                        g_free(yyvsp[-1].id);
                                        ;
     break;}
-case 64:
-#line 522 "parse.y"
+case 74:
+#line 671 "parse.y"
 {
                        if(strcmp(yyvsp[-2].id,"first")==0)
                                yyval.sigtype = SIGNAL_FIRST_METHOD;
@@ -1547,47 +1731,47 @@ case 64:
                        g_free(yyvsp[-2].id);
                                        ;
     break;}
-case 65:
-#line 534 "parse.y"
+case 75:
+#line 683 "parse.y"
 {
                        yyval.sigtype = SIGNAL_LAST_METHOD;
                                        ;
     break;}
-case 66:
-#line 537 "parse.y"
+case 76:
+#line 686 "parse.y"
 {
                        /* the_scope was default thus public */
                        the_scope = PUBLIC_SCOPE;
                                        ;
     break;}
-case 67:
-#line 543 "parse.y"
+case 77:
+#line 692 "parse.y"
 {
                        gtktypes = g_list_prepend(gtktypes,yyvsp[-3].id);
                                                ;
     break;}
-case 68:
-#line 548 "parse.y"
+case 78:
+#line 697 "parse.y"
 {
                        gtktypes = g_list_append(gtktypes,yyvsp[0].id);
                                                ;
     break;}
-case 69:
-#line 551 "parse.y"
+case 79:
+#line 700 "parse.y"
 { 
                        gtktypes = g_list_append(gtktypes,yyvsp[0].id);
                                                        ;
     break;}
-case 70:
-#line 556 "parse.y"
+case 80:
+#line 705 "parse.y"
 { yyval.cbuf = yyvsp[0].cbuf; ;
     break;}
-case 71:
-#line 557 "parse.y"
+case 81:
+#line 706 "parse.y"
 { yyval.cbuf = NULL; ;
     break;}
-case 72:
-#line 561 "parse.y"
+case 82:
+#line 710 "parse.y"
 {
                        if(!has_self) {
                                yyerror(_("signal without 'self' as "
@@ -1599,8 +1783,8 @@ case 72:
                                      ccode_line, vararg, yyvsp[-8].list);
                                                                        ;
     break;}
-case 73:
-#line 571 "parse.y"
+case 83:
+#line 720 "parse.y"
 {
                        if(!has_self) {
                                yyerror(_("signal without 'self' as "
@@ -1612,8 +1796,8 @@ case 73:
                                      ccode_line, vararg, yyvsp[-8].list);
                                                                        ;
     break;}
-case 74:
-#line 581 "parse.y"
+case 84:
+#line 730 "parse.y"
 {
                        if(!has_self) {
                                yyerror(_("virtual method without 'self' as "
@@ -1625,8 +1809,8 @@ case 74:
                                      ccode_line, vararg, NULL);
                                                                        ;
     break;}
-case 75:
-#line 591 "parse.y"
+case 85:
+#line 740 "parse.y"
 {
                        if(!has_self) {
                                yyerror(_("virtual method without 'self' as "
@@ -1638,8 +1822,8 @@ case 75:
                                      ccode_line, vararg, NULL);
                                                                        ;
     break;}
-case 76:
-#line 601 "parse.y"
+case 86:
+#line 750 "parse.y"
 {
                        if(!has_self) {
                                yyerror(_("virtual method without 'self' as "
@@ -1651,8 +1835,8 @@ case 76:
                                      ccode_line, vararg, NULL);
                                                                        ;
     break;}
-case 77:
-#line 611 "parse.y"
+case 87:
+#line 760 "parse.y"
 {
                        push_function(NO_SCOPE, OVERRIDE_METHOD, yyvsp[-8].id,
                                      yyvsp[-5].id, yyvsp[-1].id, yyvsp[0].cbuf,
@@ -1660,16 +1844,16 @@ case 77:
                                      vararg, NULL);
                                                                        ;
     break;}
-case 78:
-#line 617 "parse.y"
+case 88:
+#line 766 "parse.y"
 {
                        push_function(the_scope, REGULAR_METHOD, NULL, yyvsp[-5].id,
                                      yyvsp[-1].id, yyvsp[0].cbuf, yyvsp[-7].line, ccode_line,
                                      vararg, NULL);
                                                                ;
     break;}
-case 79:
-#line 622 "parse.y"
+case 89:
+#line 771 "parse.y"
 {
                        if(strcmp(yyvsp[-4].id,"init")==0) {
                                push_init_arg(yyvsp[-2].id,FALSE);
@@ -1690,27 +1874,27 @@ case 79:
                        }
                                                ;
     break;}
-case 80:
-#line 643 "parse.y"
+case 90:
+#line 792 "parse.y"
 { yyval.id = yyvsp[0].id; ;
     break;}
-case 81:
-#line 644 "parse.y"
+case 91:
+#line 793 "parse.y"
 {
                        yyval.id = (yyvsp[0].cbuf)->str;
                        g_string_free(yyvsp[0].cbuf,FALSE);
                                        ;
     break;}
-case 82:
-#line 648 "parse.y"
+case 92:
+#line 797 "parse.y"
 { yyval.id = NULL; ;
     break;}
-case 83:
-#line 651 "parse.y"
+case 93:
+#line 800 "parse.y"
 { vararg = FALSE; has_self = FALSE; ;
     break;}
-case 84:
-#line 652 "parse.y"
+case 94:
+#line 801 "parse.y"
 {
                        vararg = FALSE;
                        has_self = TRUE;
@@ -1723,8 +1907,8 @@ case 84:
                        }
                                                ;
     break;}
-case 85:
-#line 663 "parse.y"
+case 95:
+#line 812 "parse.y"
 {
                        has_self = TRUE;
                        if(strcmp(yyvsp[-2].id,"self")==0)
@@ -1736,40 +1920,40 @@ case 85:
                        }
                                        ;
     break;}
-case 86:
-#line 673 "parse.y"
+case 96:
+#line 822 "parse.y"
 { has_self = FALSE; ;
     break;}
-case 87:
-#line 676 "parse.y"
+case 97:
+#line 825 "parse.y"
 { vararg = TRUE; ;
     break;}
-case 88:
-#line 677 "parse.y"
+case 98:
+#line 826 "parse.y"
 { vararg = FALSE; ;
     break;}
-case 89:
-#line 680 "parse.y"
+case 99:
+#line 829 "parse.y"
 { ; ;
     break;}
-case 90:
-#line 681 "parse.y"
+case 100:
+#line 830 "parse.y"
 { ; ;
     break;}
-case 91:
-#line 684 "parse.y"
+case 101:
+#line 833 "parse.y"
 {
                        push_funcarg(yyvsp[0].id,NULL);
                                                                ;
     break;}
-case 92:
-#line 687 "parse.y"
+case 102:
+#line 836 "parse.y"
 {
                        push_funcarg(yyvsp[-1].id,yyvsp[0].id);
                                                                ;
     break;}
-case 93:
-#line 690 "parse.y"
+case 103:
+#line 839 "parse.y"
 {
                        if(strcmp(yyvsp[-2].id,"check")!=0) {
                                yyerror(_("parse error"));
@@ -1779,8 +1963,8 @@ case 93:
                        push_funcarg(yyvsp[-4].id,NULL);
                                                                ;
     break;}
-case 94:
-#line 698 "parse.y"
+case 104:
+#line 847 "parse.y"
 {
                        if(strcmp(yyvsp[-2].id,"check")!=0) {
                                yyerror(_("parse error"));
@@ -1790,16 +1974,16 @@ case 94:
                        push_funcarg(yyvsp[-5].id,yyvsp[-4].id);
                                                                ;
     break;}
-case 95:
-#line 708 "parse.y"
+case 105:
+#line 857 "parse.y"
 { ; ;
     break;}
-case 96:
-#line 709 "parse.y"
+case 106:
+#line 858 "parse.y"
 { ; ;
     break;}
-case 97:
-#line 712 "parse.y"
+case 107:
+#line 861 "parse.y"
 {
                        if(strcmp(yyvsp[0].id,"type")==0) {
                                Node *node = new_check(TYPE_CHECK,NULL);
@@ -1814,61 +1998,61 @@ case 97:
                        g_free(yyvsp[0].id);
                                        ;
     break;}
-case 98:
-#line 725 "parse.y"
+case 108:
+#line 874 "parse.y"
 {
                        Node *node = new_check(GT_CHECK,yyvsp[0].id);
                        checks = g_list_append(checks,node);
                                        ;
     break;}
-case 99:
-#line 729 "parse.y"
+case 109:
+#line 878 "parse.y"
 {
                        Node *node = new_check(LT_CHECK,yyvsp[0].id);
                        checks = g_list_append(checks,node);
                                        ;
     break;}
-case 100:
-#line 733 "parse.y"
+case 110:
+#line 882 "parse.y"
 {
                        Node *node = new_check(GE_CHECK,yyvsp[0].id);
                        checks = g_list_append(checks,node);
                                        ;
     break;}
-case 101:
-#line 737 "parse.y"
+case 111:
+#line 886 "parse.y"
 {
                        Node *node = new_check(LE_CHECK,yyvsp[0].id);
                        checks = g_list_append(checks,node);
                                        ;
     break;}
-case 102:
-#line 741 "parse.y"
+case 112:
+#line 890 "parse.y"
 {
                        Node *node = new_check(EQ_CHECK,yyvsp[0].id);
                        checks = g_list_append(checks,node);
                                        ;
     break;}
-case 103:
-#line 745 "parse.y"
+case 113:
+#line 894 "parse.y"
 {
                        Node *node = new_check(NE_CHECK,yyvsp[0].id);
                        checks = g_list_append(checks,node);
                                        ;
     break;}
-case 104:
-#line 751 "parse.y"
+case 114:
+#line 900 "parse.y"
 { yyval.id = yyvsp[0].id; ;
     break;}
-case 105:
-#line 752 "parse.y"
+case 115:
+#line 901 "parse.y"
 {
                        yyval.id = g_strconcat("-",yyvsp[0].id,NULL);
                        g_free(yyvsp[0].id);
                                        ;
     break;}
-case 106:
-#line 756 "parse.y"
+case 116:
+#line 905 "parse.y"
 { yyval.id = yyvsp[0].id; ;
     break;}
 }
@@ -2093,5 +2277,5 @@ yyerrhandle:
     }
   return 1;
 }
-#line 759 "parse.y"
+#line 908 "parse.y"
 
index 63f0a7a1d21e743c9051b6c571785fe2ed23c3a0..d0b56fe85679f1783dec67f2858fddcf61af6841 100644 (file)
@@ -43,6 +43,13 @@ static GList *checks = NULL;
 static int has_self = FALSE;
 static int vararg = FALSE;
 
+/* destructor and initializer for variables */
+static char *destructor = NULL;
+static int destructor_line = 0;
+static gboolean destructor_simple = TRUE;
+static char *initializer = NULL;
+static int initializer_line = 0;
+
 static GList *gtktypes = NULL;
 
 /* this can be a global as we will only do one function at a time
@@ -98,7 +105,10 @@ push_variable(char *name, int scope, int line_no, char *postfix)
 
        type->postfix = postfix;
        
-       var = new_variable(scope,type,name,line_no);
+       var = new_variable(scope, type, name, line_no,
+                          destructor, destructor_line,
+                          destructor_simple,
+                          initializer, initializer_line);
        class_nodes = g_list_append(class_nodes, var);
 }
 
@@ -198,6 +208,29 @@ push_self(char *id)
        funcargs = g_list_prepend(funcargs, node);
 }
 
+static Variable *
+find_var_or_die(const char *id, int line)
+{
+       GList *li;
+       char *s;
+
+       for(li = class_nodes; li != NULL; li = li->next) {
+               Variable *var;
+               Node *node = li->data;
+               if(node->type != VARIABLE_NODE)
+                       continue;
+               var = li->data;
+               if(strcmp(var->id, id)==0)
+                       return var;
+       }
+
+       s = g_strdup_printf(_("Variable %s not defined here"), id);
+       print_error(FALSE, s, line);
+
+       g_assert_not_reached();
+       return NULL;
+}
+
 %}
 
 %union {
@@ -284,12 +317,14 @@ classdec: CLASS TYPETOKEN FROM TYPETOKEN  {
                                                }
        ;
        
-classcode:     classcode method                { ; }
-       |       classcode variable              { ; }
-       |       classcode argument              { ; }
-       |       method                          { ; }
+classcode:     classcode thing                 { ; }
+       |       thing                           { ; }
+       ;
+
+thing:                 method                          { ; }
        |       variable                        { ; }
        |       argument                        { ; }
+       |       ';'                             { ; }
        ;
 
 scope:         PUBLIC                  { the_scope = PUBLIC_SCOPE; }
@@ -297,11 +332,62 @@ scope:            PUBLIC                  { the_scope = PUBLIC_SCOPE; }
        |       PROTECTED               { the_scope = PROTECTED_SCOPE; }
        ;
 
-variable:      scope type TOKEN ';'            {
-                       push_variable($<id>3,the_scope,$<line>1,NULL);
+destructor:    TOKEN TOKEN     {
+                       if(strcmp($<id>1, "destroywith")==0) {
+                               g_free($<id>1);
+                               destructor = $<id>2;
+                               destructor_line = ccode_line;
+                               destructor_simple = TRUE;
+                       } else {
+                               g_free($<id>1);
+                               g_free($<id>2);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                               }
+       |       TOKEN '{' CCODE         {
+                       if(strcmp($<id>1, "destroy")==0) {
+                               g_free($<id>1);
+                               destructor = ($<cbuf>3)->str;
+                               g_string_free($<cbuf>3, FALSE);
+                               destructor_line = ccode_line;
+                               destructor_simple = FALSE;
+                       } else {
+                               g_free($<id>1);
+                               g_string_free($<cbuf>3, TRUE);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                                       }
+       ;
+
+initializer:   '=' numtok      {
+                       initializer = $<id>2;
+                       initializer_line = ccode_line;
+                               }
+       |       '=' '{' CCODE   {
+                       initializer = ($<cbuf>3)->str;
+                       initializer_line = ccode_line;
+                       g_string_free($<cbuf>3, FALSE);
+                               }
+       ;
+
+
+varoptions:    destructor initializer  { ; }
+       |       initializer destructor  { ; }
+       |       initializer             { destructor = NULL; }
+       |       destructor              { initializer = NULL; }
+       |                               {
+                       destructor = NULL;
+                       initializer = NULL;
+                                       }
+       ;
+
+variable:      scope type TOKEN varoptions ';'         {
+                       push_variable($<id>3, the_scope,$<line>1, NULL);
                                                }
-       |       scope type TOKEN ARRAY_DIM ';'  {
-                       push_variable($<id>3,the_scope,$<line>1,$<id>4);
+       |       scope type TOKEN ARRAY_DIM varoptions ';'       {
+                       push_variable($<id>3, the_scope, $<line>1, $<id>4);
                                                }
        ;
 argument:      ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' {
@@ -367,6 +453,69 @@ argument:  ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' {
                                YYERROR;
                        }
                                                }
+       |       ARGUMENT flags argtype TOKEN TOKEN {
+                       Node *node;
+                       char *get, *set;
+                       Variable *var;
+                       Type *type;
+                       char *root;
+                       
+                       if(strcmp($<id>5,"link")!=0 &&
+                          strcmp($<id>5,"stringlink")!=0 &&
+                          strcmp($<id>5,"objectlink")!=0) {
+                               g_free($<id>5); g_free($<id>3);
+                               g_free($<id>4);
+                               g_list_foreach($<list>2,(GFunc)g_free,NULL);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+
+                       type = pop_type();
+
+                       var = find_var_or_die($<id>4, $<line>1);
+                       if(var->scope == PRIVATE_SCOPE)
+                               root = "self->_priv";
+                       else
+                               root = "self";
+
+                       if(strcmp($<id>5,"link")==0) {
+                               set = g_strdup_printf("%s->%s = ARG;",
+                                                     root, $<id>4);
+                       } else if(strcmp($<id>5,"stringlink")==0) {
+                               set = g_strdup_printf("g_free(%s->%s); "
+                                                     "%s->%s = g_strdup(ARG);",
+                                                     root, $<id>4,
+                                                     root, $<id>4);
+                       } else if(strcmp($<id>5,"objectlink")==0) {
+                               set = g_strdup_printf(
+                                 "if(%s->%s) "
+                                  "gtk_object_unref(GTK_OBJECT(%s->%s)); "
+                                 "%s->%s = ARG; "
+                                 "if(%s->%s) "
+                                  "gtk_object_ref(GTK_OBJECT(%s->%s)); ",
+                                 root, $<id>4,
+                                 root, $<id>4,
+                                 root, $<id>4,
+                                 root, $<id>4,
+                                 root, $<id>4);
+                       } else {
+                               g_assert_not_reached();
+                       }
+
+                       /* get is the same for everything */
+                       get = g_strdup_printf("ARG = %s->%s;", root, $<id>4);
+
+                       g_free($<id>5);
+
+
+                       if(!type)
+                               type = copy_type(var->vtype);
+
+                       node = new_argument($<id>3, type, $<list>2,
+                                           $<id>4, get, $<line>1,
+                                           set, $<line>1, $<line>1);
+                       class_nodes = g_list_append(class_nodes,node);
+                                               }
        ;
 
 argtype:       TOKEN '(' TOKEN type ')'        {
index e805824877246dc0155fad9d0777dde70d298ccd..402f69ccb839a18d959c8f2fe814875e436f0764 100644 (file)
@@ -3,7 +3,7 @@
    look in here to see a whole array of different syntax options, but
    don't expect this to be an easy to read file */
 
-requires 0.92.1
+requires 0.93.0
 
 %headertop{
 /* this should go on the very top of the header */
@@ -46,6 +46,25 @@ void bubu(void);
 class Gtk:Weird:Button from Gtk:Button {
        public int i;
        argument INT i set { self->i = ARG; } get { ARG = self->i; } ;
+
+       public int testing = 1;
+       argument INT testing link;
+
+       public char * testingstring = {g_strdup("test")}
+               destroywith g_free;
+       argument POINTER testingstring stringlink;
+
+       public Gtk:Weird:Button * testingobj
+               destroywith gtk_object_unref;
+       argument POINTER testingobj objectlink;
+
+       public Gtk:Object * testingobj2
+               destroy {
+                       if(VAR)
+                               gtk_object_unref(GTK_OBJECT(VAR));
+               };
+       argument POINTER (type Gtk:Object *) testingobj2 objectlink;
+       
        argument POINTER (type GtkObject *) some_object
                set { /* set some_object */ }
                get { /* get some_object */
@@ -258,6 +277,10 @@ class Gtk:Weird:Button from Gtk:Button {
                /*foo*/
                return w;
        }
+       /* testing empty statements */
+       ;
+       ;
+       ;
 }
 
 %{
index b92f771024fa3e21197f645b1bd039e86fa0a43e..6382d05979e56044c5e4e4161e640ab24ead2514 100644 (file)
@@ -119,7 +119,10 @@ new_argument(char *gtktype, Type *atype, GList *flags, char *name, char *get, in
 }
 
 Node *
-new_variable(int scope, Type *vtype, char *id, int line_no)
+new_variable(int scope, Type *vtype, char *id, int line_no,
+            char *destructor, int destructor_line,
+            gboolean destructor_simple,
+            char *initializer, int initializer_line)
 {
        Variable *node = (Variable *)g_new(Node,1);
        node->type = VARIABLE_NODE;
@@ -127,5 +130,24 @@ new_variable(int scope, Type *vtype, char *id, int line_no)
        node->vtype = vtype;
        node->id = id;
        node->line_no = line_no;
+       node->destructor = destructor;
+       node->destructor_line = destructor_line;
+       node->destructor_simple = destructor_simple;
+       node->initializer = initializer;
+       node->initializer_line = initializer_line;
        return (Node *)node;
 }
+
+Type *
+copy_type(Type *type)
+{
+       Node *node;
+
+       if(!type) return NULL;
+
+       node = new_type(type->stars,
+                       g_strdup(type->name),
+                       g_strdup(type->postfix));
+
+       return (Type *)node;
+}
index 9d3638fa2966265ba76521b62d148fdb43f867a0..66d181976c505ba422acf2b5aae09f269890b4fd 100644 (file)
@@ -155,6 +155,11 @@ struct _Variable {
        Type *vtype;
        char *id;
        int line_no;
+       char *destructor;
+       int destructor_line;
+       gboolean destructor_simple;
+       char *initializer;
+       int initializer_line;
 };
 
 union _Node {
@@ -180,6 +185,11 @@ Node *new_method(int scope, int method, Type *mtype, char *otype,
 Node *new_argument(char *gtktype, Type *atype, GList *flags, char *name,
                   char *get, int get_line, char *set, int set_line,
                   int line_no);
-Node *new_variable(int scope, Type *vtype, char *id,int line_no);
+Node *new_variable(int scope, Type *vtype, char *id, int line_no,
+                  char *destructor, int destructor_line,
+                  gboolean destructor_simple,
+                  char *initializer, int initializer_line);
+
+Type *copy_type(Type *type);
 
 #endif