X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/4f7cfa972623842e64e3a8468696f1f6f40fd202..02cf98875fd0b8462ce39778db16cfd347b5c2d0:/src/parse.y diff --git a/src/parse.y b/src/parse.y index 17ab264..46df2d6 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1,5 +1,7 @@ /* GOB C Preprocessor - * Copyright (C) 1999 the Free Software Foundation. + * Copyright (C) 1999-2000 the Free Software Foundation. + * Copyright (C) 2000 Eazel, Inc. + * Copyright (C) 2001-2009 George (Jiri) Lebl * * Author: George Lebl * @@ -20,40 +22,58 @@ */ %{ -#include "config.h" +#include #include #include +#include #include #include "treefuncs.h" #include "main.h" #include "util.h" +/* FIXME: add gettext support */ #define _(x) (x) GList *nodes = NULL; static GList *class_nodes = NULL; Node *class = NULL; - +GList *enums = NULL; +static GList *enum_vals = NULL; +static GList *flag_vals = NULL; +static GList *error_vals = NULL; + +static gboolean abstract = FALSE; +static gboolean dynamic = FALSE; +static char *chunk_size = NULL; +static char *bonobo_object_class = NULL; +static int glade_xml = FALSE; +static GList *interfaces = NULL; static GList *typestack = NULL; -static int stars = 0; static GList *funcargs = NULL; static GList *checks = NULL; static int has_self = FALSE; static int vararg = FALSE; +static Method *last_added_method = NULL; /* destructor and initializer for variables */ +static gboolean destructor_unref = FALSE; static char *destructor = NULL; static int destructor_line = 0; static gboolean destructor_simple = TRUE; static char *initializer = NULL; static int initializer_line = 0; +static int glade_widget = FALSE; +static char *funcattrs = NULL; static char *onerror = NULL; static char *defreturn = NULL; static GList *gtktypes = NULL; +static char *signal_name=NULL; + +static Property *property = NULL; /* this can be a global as we will only do one function at a time anyway */ @@ -64,6 +84,7 @@ int yylex(void); extern int ccode_line; extern int line_no; +extern gboolean for_cpp; extern char *yytext; @@ -73,9 +94,10 @@ yyerror(char *str) char *out=NULL; char *p; - if(strcmp(yytext,"\n")==0) { - out=g_strconcat("Error: ",str," before newline",NULL); - } else if(yytext[0]=='\0') { + if (strcmp (yytext, "\n") == 0 || + strcmp (yytext, "\r") == 0) { + out = g_strconcat ("Error: ", str, " before end of line", NULL); + } else if (yytext[0] == '\0') { out=g_strconcat("Error: ", str, " at end of input", NULL); } else { char *tmp = g_strdup(yytext); @@ -101,24 +123,35 @@ pop_type(void) } static void -push_variable(char *name, int scope, int line_no, char *postfix) +push_variable (char *name, int scope, int line_no, char *postfix) { Node *var; - Type *type = pop_type(); + Type *type = pop_type (); type->postfix = postfix; - var = new_variable(scope, type, name, line_no, - destructor, destructor_line, - destructor_simple, - initializer, initializer_line); + var = node_new (VARIABLE_NODE, + "scope", scope, + "vtype:steal", type, + "glade_widget", glade_widget, + "id:steal", name, + "line_no", line_no, + "destructor_unref", destructor_unref, + "destructor:steal", destructor, + "destructor_line", destructor_line, + "destructor_simple", destructor_simple, + "initializer:steal", initializer, + "initializer_line", initializer_line, + "initializer_simple", TRUE, + NULL); class_nodes = g_list_append(class_nodes, var); + glade_widget = FALSE; } static void -push_function(int scope, int method, char *oid, char *id, - GString *cbuf, int line_no, int ccode_line, - gboolean vararg, GList *flags) +push_function (int scope, int method, char *oid, char *id, + GString *cbuf, int line_no, int ccode_line, + gboolean vararg, GList *flags) { Node *node; Type *type; @@ -126,10 +159,16 @@ push_function(int scope, int method, char *oid, char *id, g_assert(scope != CLASS_SCOPE); - if(method!=INIT_METHOD && method!=CLASS_INIT_METHOD) { - type = pop_type(); + if(method == INIT_METHOD || + method == CLASS_INIT_METHOD || + method == CONSTRUCTOR_METHOD || + method == DISPOSE_METHOD || + method == FINALIZE_METHOD) { + type = (Type *)node_new (TYPE_NODE, + "name", "void", + NULL); } else { - type = (Type *)new_type(0,g_strdup("void"),NULL); + type = pop_type(); } /* a complicated and ugly test to figure out if we have @@ -140,18 +179,18 @@ push_function(int scope, int method, char *oid, char *id, !(g_list_length(funcargs) == 1 && g_list_length(gtktypes) == 2 && strcmp(gtktypes->next->data, "NONE")==0)) { - print_error(TRUE, _("The number of GTK arguments and " - "function arguments for a signal " - "don't seem to match"), line_no); + error_print(GOB_WARN, line_no, + _("The number of GTK arguments and " + "function arguments for a signal " + "don't seem to match")); } if(g_list_length(gtktypes) > 2) { GList *li; for(li = gtktypes->next; li; li = li->next) { if(strcmp(li->data, "NONE")==0) { - print_error(FALSE, + error_print(GOB_ERROR, line_no, _("NONE can only appear in an " - "argument list by itself"), - line_no); + "argument list by itself")); } } } @@ -165,9 +204,34 @@ push_function(int scope, int method, char *oid, char *id, } else c_cbuf = NULL; - node = new_method(scope, method, type, oid, gtktypes, flags, - id, funcargs, onerror, defreturn, c_cbuf, line_no, - ccode_line, vararg); + if (signal_name == NULL ) + { + GString * buffer=g_string_new(""); + g_string_printf(buffer, "\"%s\"", id); + signal_name = buffer->str; + g_string_free(buffer, FALSE); + } + node = node_new (METHOD_NODE, + "scope", scope, + "method", method, + "mtype:steal", type, + "otype:steal", oid, + "gtktypes:steal", gtktypes, + "flags:steal", flags, + "id:steal", id, + "signal_name:steal", signal_name, + "args:steal", funcargs, + "funcattrs:steal", funcattrs, + "onerror:steal", onerror, + "defreturn:steal", defreturn, + "cbuf:steal", c_cbuf, + "line_no", line_no, + "ccode_line", ccode_line, + "vararg", vararg, + "unique_id", method_unique_id++, + NULL); + + last_added_method = (Method *)node; if(cbuf) g_string_free(cbuf, @@ -175,8 +239,9 @@ push_function(int scope, int method, char *oid, char *id, above */ c_cbuf?FALSE:TRUE); gtktypes = NULL; + signal_name = NULL; funcargs = NULL; - + funcattrs = NULL; onerror = NULL; defreturn = NULL; @@ -186,16 +251,21 @@ push_function(int scope, int method, char *oid, char *id, static void free_all_global_state(void) { + g_free(funcattrs); + funcattrs = NULL; g_free(onerror); onerror = NULL; g_free(defreturn); defreturn = NULL; + g_free(chunk_size); + chunk_size = NULL; + g_list_foreach(gtktypes, (GFunc)g_free, NULL); g_list_free(gtktypes); gtktypes = NULL; - free_node_list(funcargs); + node_list_free (funcargs); funcargs = NULL; } @@ -207,7 +277,11 @@ push_funcarg(char *name, char *postfix) type->postfix = postfix; - node = new_funcarg(type, name, checks); + node = node_new (FUNCARG_NODE, + "atype:steal", type, + "name:steal", name, + "checks:steal", checks, + NULL); checks = NULL; funcargs = g_list_append(funcargs, node); @@ -225,21 +299,38 @@ push_init_arg(char *name, int is_class) else tn = g_strdup(((Class *)class)->otype); - type = new_type(1,tn,NULL); - node = new_funcarg((Type *)type,name,NULL); + type = node_new (TYPE_NODE, + "name:steal", tn, + "pointer", "*", + NULL); + node = node_new (FUNCARG_NODE, + "atype:steal", (Type *)type, + "name:steal", name, + NULL); funcargs = g_list_prepend(funcargs, node); } static void -push_self(char *id) +push_self(char *id, gboolean constant) { Node *node; Node *type; GList *ch = NULL; - type = new_type(1,g_strdup(((Class *)class)->otype),NULL); - ch = g_list_append(ch,new_check(NULL_CHECK,NULL)); - ch = g_list_append(ch,new_check(TYPE_CHECK,NULL)); - node = new_funcarg((Type *)type,id,ch); + type = node_new (TYPE_NODE, + "name", ((Class *)class)->otype, + "pointer", constant ? "const *" : "*", + NULL); + ch = g_list_append (ch, node_new (CHECK_NODE, + "chtype", NULL_CHECK, + NULL)); + ch = g_list_append (ch, node_new (CHECK_NODE, + "chtype", TYPE_CHECK, + NULL)); + node = node_new (FUNCARG_NODE, + "atype:steal", (Type *)type, + "name:steal", id, + "checks:steal", ch, + NULL); funcargs = g_list_prepend(funcargs, node); } @@ -247,7 +338,6 @@ 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; @@ -259,17 +349,22 @@ find_var_or_die(const char *id, int line) return var; } - s = g_strdup_printf(_("Variable %s not defined here"), id); - print_error(FALSE, s, line); + error_printf(GOB_ERROR, line, _("Variable %s not defined here"), id); g_assert_not_reached(); return NULL; } static gboolean -set_return_value(char *type, char *val) +set_attr_value(char *type, char *val) { - if(strcmp(type, "onerror")==0) { + if(strcmp(type, "attr")==0) { + if(!funcattrs) { + funcattrs = val; + return TRUE; + } else + return FALSE; + } else if(strcmp(type, "onerror")==0) { if(!onerror) { onerror = val; return TRUE; @@ -285,6 +380,314 @@ set_return_value(char *type, char *val) return FALSE; } +static void +export_accessors (const char *var_name, + gboolean do_get, + int get_lineno, + gboolean do_set, + int set_lineno, + Type *type, + const char *gtktype, + int lineno) +{ + Type *the_type; + + if (type != NULL) + the_type = (Type *)node_copy ((Node *)type); + else + the_type = get_tree_type (gtktype, TRUE); + + if (the_type == NULL) { + error_print (GOB_ERROR, line_no, + _("Cannot determine type of property or argument")); + return; + } + + if (do_get) { + char *get_id = g_strdup_printf ("get_%s", var_name); + GString *get_cbuf = g_string_new (NULL); + Node *node1 = node_new (TYPE_NODE, + "name", the_type->name, + "pointer", the_type->pointer, + "postfix", the_type->postfix, + NULL); + Node *node3 = node_new (TYPE_NODE, + "name", class->class.otype, + "pointer", "*", + NULL); + + g_string_printf(get_cbuf, + "\t%s%s val; " + "g_object_get (G_OBJECT (self), \"%s\", " + "&val, NULL); " + "return val;\n", + the_type->name, + the_type->pointer ? the_type->pointer : "", + var_name); + + typestack = g_list_prepend (typestack, node1); + typestack = g_list_prepend (typestack, node3); + + push_funcarg ("self", FALSE); + + push_function (PUBLIC_SCOPE, REGULAR_METHOD, NULL, + get_id, get_cbuf, get_lineno, + lineno, FALSE, NULL); + } + + if (do_set) { + char *set_id = g_strdup_printf ("set_%s", var_name); + GString *set_cbuf = g_string_new (NULL); + Node *node1 = node_new (TYPE_NODE, + "name", the_type->name, + "pointer", the_type->pointer, + "postfix", the_type->postfix, + NULL); + Node *node2 = node_new (TYPE_NODE, + "name", "void", + NULL); + Node *node3 = node_new (TYPE_NODE, + "name", class->class.otype, + "pointer", "*", + NULL); + + g_string_printf(set_cbuf, + "\tg_object_set (G_OBJECT (self), " + "\"%s\", val, NULL);\n", + var_name); + + typestack = g_list_prepend (typestack, node2); + typestack = g_list_prepend (typestack, node1); + typestack = g_list_prepend (typestack, node3); + + push_funcarg ("self", FALSE); + push_funcarg ("val", FALSE); + + typestack = g_list_prepend (typestack, node2); + push_function (PUBLIC_SCOPE, REGULAR_METHOD, NULL, + set_id, set_cbuf, set_lineno, + lineno, FALSE, NULL); + } + + node_free ((Node *)the_type); +} + +static char * +get_prop_enum_flag_cast (Property *prop) +{ + char *tmp, *ret; + if (prop->extra_gtktype == NULL || + /* HACK! just in case someone made this + * work with 2.0.0 by using the TYPE + * macro directly */ + ((strstr (prop->extra_gtktype, "_TYPE_") != NULL || + strstr (prop->extra_gtktype, "TYPE_") == prop->extra_gtktype) && + strchr (prop->extra_gtktype, ':') == NULL)) { + if (prop->ptype != NULL) + return get_type (prop->ptype, TRUE); + else + return g_strdup (""); + } + tmp = remove_sep (prop->extra_gtktype); + ret = g_strdup_printf ("(%s) ", tmp); + g_free (tmp); + return ret; +} + +static void +add_construct_glade (char * file, char * root, char * domain) +{ + Node *var; + Type * type; + + type = (Type *)node_new (TYPE_NODE, + "name", "GladeXML", + "pointer", "*", + NULL); + initializer = g_strdup_printf("\t{\n" + "\tGtkWidget * root;\n" + "\t%%1$s->_priv->_glade_xml = glade_xml_new(%s, %s, %s);\n" + "\troot = glade_xml_get_widget(%%1$s->_priv->_glade_xml, %s);\n" + "\tgtk_widget_show(root);\n" + "\tgtk_container_add(GTK_CONTAINER(%%1$s), root);\n" + "\tglade_xml_signal_autoconnect_full(%%1$s->_priv->_glade_xml, (GladeXMLConnectFunc)___glade_xml_connect_foreach, (gpointer)%%1$s);\n" + "}\n", file, root, domain ? domain : "NULL", root); + + var = node_new (VARIABLE_NODE, + "scope", PRIVATE_SCOPE, + "vtype:steal", type, + "glade_widget", FALSE, + "id:steal", "_glade_xml", + "destructor_unref", FALSE, + "destructor", "g_object_unref", + "destructor_simple", TRUE, + "initializer", initializer, + "initializer_simple", FALSE, + NULL); + class_nodes = g_list_prepend(class_nodes, var); +} + +static void +property_link_and_export (Node *node) +{ + Property *prop = (Property *)node; + + if (prop->link) { + const char *root; + char *get = NULL, *set = NULL; + Variable *var; + + if (prop->set != NULL || + prop->get != NULL) { + error_print (GOB_ERROR, prop->line_no, + _("Property linking requested, but " + "getters and setters exist")); + } + + var = find_var_or_die (prop->name, prop->line_no); + if(var->scope == PRIVATE_SCOPE) { + root = "self->_priv"; + } else if (var->scope == CLASS_SCOPE) { + root = "SELF_GET_CLASS(self)"; + if (no_self_alias) + error_print (GOB_ERROR, prop->line_no, + _("Self aliases needed when autolinking to a classwide member")); + } else { + root = "self"; + } + + if (strcmp (prop->gtktype, "STRING") == 0) { + set = g_strdup_printf("{ char *old = %s->%s; " + "%s->%s = g_value_dup_string (VAL); g_free (old); }", + root, prop->name, + root, prop->name); + get = g_strdup_printf("g_value_set_string (VAL, %s->%s);", + root, prop->name); + } else if (strcmp (prop->gtktype, "OBJECT") == 0) { + char *cast; + if (prop->extra_gtktype != NULL) { + cast = remove_sep (prop->extra_gtktype); + } else { + cast = g_strdup ("void"); + } + set = g_strdup_printf("{ GObject *___old = (GObject *)%s->%s; " + "%s->%s = (%s *)g_value_dup_object (VAL); " + "if (___old != NULL) { " + "g_object_unref (G_OBJECT (___old)); " + "} " + "}", + root, prop->name, + root, prop->name, + cast); + get = g_strdup_printf ("g_value_set_object (VAL, " + "(gpointer)%s->%s);", + root, prop->name); + g_free (cast); + } else if (strcmp (prop->gtktype, "BOXED") == 0) { + char *type = make_me_type (prop->extra_gtktype, + "G_TYPE_BOXED"); + if (prop->extra_gtktype == NULL) { + error_print (GOB_ERROR, prop->line_no, + _("Property linking requested for BOXED, but " + "boxed_type not set")); + } + set = g_strdup_printf("{ gpointer ___old = (gpointer)%s->%s; " + "gpointer ___new = (gpointer)g_value_get_boxed (VAL); " + "if (___new != ___old) { " + "if (___old != NULL) g_boxed_free (%s, ___old); " + "if (___new != NULL) %s->%s = g_boxed_copy (%s, ___new); " + "else %s->%s = NULL;" + "} " + "}", + root, prop->name, + type, + root, prop->name, + type, + root, prop->name); + get = g_strdup_printf("g_value_set_boxed (VAL, %s->%s);", + root, prop->name); + g_free (type); + } else { + char *set_func; + char *get_func; + const char *getcast = ""; + const char *setcast = ""; + char *to_free = NULL; + set_func = g_strdup_printf ("g_value_set_%s", prop->gtktype); + gob_strdown (set_func); + get_func = g_strdup_printf ("g_value_get_%s", prop->gtktype); + gob_strdown (get_func); + + if (for_cpp) { + if (strcmp (prop->gtktype, "FLAGS") == 0) { + setcast = "(guint) "; + getcast = to_free = + get_prop_enum_flag_cast (prop); + } else if (strcmp (prop->gtktype, "ENUM") == 0) { + setcast = "(gint) "; + getcast = to_free = + get_prop_enum_flag_cast (prop); + } else if (strcmp (prop->gtktype, "POINTER") == 0) { + setcast = "(gpointer) "; + getcast = g_strdup_printf ("(%s%s) ", + prop->ptype->name, + prop->ptype->pointer ? prop->ptype->pointer : ""); + } + } + + set = g_strdup_printf("%s->%s = %s%s (VAL);", + root, prop->name, + getcast, + get_func); + get = g_strdup_printf("%s (VAL, %s%s->%s);", + set_func, + setcast, + root, prop->name); + + g_free (get_func); + g_free (set_func); + g_free (to_free); + } + + node_set (node, + "get:steal", get, + "get_line", prop->line_no, + "set:steal", set, + "set_line", prop->line_no, + NULL); + } + + if (prop->export) { + export_accessors (prop->name, + prop->get != NULL, prop->get_line, + prop->set != NULL, prop->set_line, + prop->ptype, + prop->gtktype, + prop->line_no); + } +} + + +static char * +debool (char *s) +{ + if (strcmp (s, "BOOL") == 0) { + error_print (GOB_WARN, line_no, + _("BOOL type is deprecated, please use BOOLEAN")); + g_free (s); + return g_strdup ("BOOLEAN"); + } else { + return s; + } +} + +static void +ensure_property (void) +{ + if (property == NULL) + property = (Property *)node_new (PROPERTY_NODE, NULL); +} + %} %union { @@ -299,9 +702,12 @@ set_return_value(char *type, char *val) %token CONST VOID STRUCT UNION ENUM THREEDOTS %token SIGNED UNSIGNED LONG SHORT INT FLOAT DOUBLE CHAR -%token TOKEN NUMBER TYPETOKEN ARRAY_DIM -%token CCODE HTCODE PHCODE HCODE ACODE ATCODE -%token PUBLIC PRIVATE PROTECTED CLASSWIDE ARGUMENT VIRTUAL SIGNAL OVERRIDE +%token TOKEN NUMBER TYPETOKEN ARRAY_DIM SINGLE_CHAR +%token CCODE CTCODE ADCODE HTCODE PHCODE HCODE ACODE ATCODE STRING +%token PUBLIC PRIVATE PROTECTED CLASSWIDE PROPERTY ARGUMENT +%token VIRTUAL SIGNAL OVERRIDE +%token NAME NICK BLURB MAXIMUM MINIMUM DEFAULT_VALUE ERROR FLAGS TYPE +%token FLAGS_TYPE ENUM_TYPE PARAM_TYPE BOXED_TYPE OBJECT_TYPE %% @@ -312,45 +718,87 @@ prog: ccodes class ccodes { ; } ; ccode: CCODE { - Node *node = new_ccode(C_CCODE,($1)->str, - ccode_line); + Node *node = node_new (CCODE_NODE, + "cctype", C_CCODE, + "cbuf:steal", ($1)->str, + "line_no", ccode_line, + NULL); + nodes = g_list_append(nodes,node); + g_string_free($1,FALSE); + } + | ADCODE { + Node *node = node_new (CCODE_NODE, + "cctype", AD_CCODE, + "cbuf:steal", ($1)->str, + "line_no", ccode_line, + NULL); nodes = g_list_append(nodes,node); g_string_free($1,FALSE); } | HCODE { - Node *node = new_ccode(H_CCODE,($1)->str, - ccode_line); + Node *node = node_new (CCODE_NODE, + "cctype", H_CCODE, + "cbuf:steal", ($1)->str, + "line_no", ccode_line, + NULL); nodes = g_list_append(nodes,node); g_string_free($1,FALSE); } | HTCODE { - Node *node = new_ccode(HT_CCODE,($1)->str, - ccode_line); + Node *node = node_new (CCODE_NODE, + "cctype", HT_CCODE, + "cbuf:steal", ($1)->str, + "line_no", ccode_line, + NULL); nodes = g_list_append(nodes,node); g_string_free($1,FALSE); } | PHCODE { - Node *node = new_ccode(PH_CCODE,($1)->str, - ccode_line); + Node *node = node_new (CCODE_NODE, + "cctype", PH_CCODE, + "cbuf:steal", ($1)->str, + "line_no", ccode_line, + NULL); nodes = g_list_append(nodes,node); g_string_free($1,FALSE); } | ACODE { - Node *node = new_ccode(A_CCODE,($1)->str, - ccode_line); + Node *node = node_new (CCODE_NODE, + "cctype", A_CCODE, + "cbuf:steal", ($1)->str, + "line_no", ccode_line, + NULL); nodes = g_list_append(nodes,node); g_string_free($1,FALSE); } | ATCODE { - Node *node = new_ccode(AT_CCODE,($1)->str, - ccode_line); + Node *node = node_new (CCODE_NODE, + "cctype", AT_CCODE, + "cbuf:steal", ($1)->str, + "line_no", ccode_line, + NULL); + nodes = g_list_append(nodes,node); + g_string_free($1,FALSE); + } + | CTCODE { + Node *node = node_new (CCODE_NODE, + "cctype", CT_CCODE, + "cbuf:steal", ($1)->str, + "line_no", ccode_line, + NULL); nodes = g_list_append(nodes,node); g_string_free($1,FALSE); } ; ccodes: ccodes ccode { ; } + | ccodes enumcode { ; } + | ccodes flagcode { ; } + | ccodes errorcode { ; } | ccode { ; } + | enumcode { ; } + | flagcode { ; } + | errorcode { ; } ; class: classdec '{' classcode '}' { @@ -365,18 +813,135 @@ class: classdec '{' classcode '}' { } ; -classdec: CLASS TYPETOKEN FROM TYPETOKEN { - class = new_class($2,$4,NULL); +classdec: CLASS TYPETOKEN FROM TYPETOKEN classflags { + class = node_new (CLASS_NODE, + "otype:steal", $2, + "ptype:steal", $4, + "bonobo_object_class:steal", bonobo_object_class, + "glade_xml", glade_xml, + "interfaces:steal", interfaces, + "chunk_size:steal", chunk_size, + "abstract", abstract, + "dynamic", dynamic, + NULL); + bonobo_object_class = NULL; + glade_xml = FALSE; + chunk_size = NULL; + interfaces = NULL; } ; - + +classflags: + | '(' TOKEN ')' classflags { + if(strcmp($2,"abstract") == 0) { + abstract = TRUE; + } else if(strcmp($2,"dynamic") == 0) { + dynamic = TRUE; + } else { + yyerror(_("parse error")); + YYERROR; + } + } + | '(' TOKEN TOKEN ')' classflags { + if(strcmp($2,"chunks") == 0) { + g_free (chunk_size); + chunk_size = g_strdup($3); + } else if(strcmp($2,"BonoboObject") == 0) { + g_free (bonobo_object_class); + bonobo_object_class = g_strdup($3); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + | '(' TOKEN TYPETOKEN ')' classflags { + if (strcmp ($2, "interface") == 0) { + interfaces = g_list_append (interfaces, + g_strdup ($3)); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + | '(' TOKEN NUMBER ')' classflags { + if(strcmp($2,"chunks") == 0) { + g_free (chunk_size); + if(atoi($3) != 0) + chunk_size = g_strdup($3); + else + chunk_size = NULL; + } else { + yyerror(_("parse error")); + YYERROR; + } + } + | '(' TOKEN STRING STRING ')' classflags { + if (strcmp ($2, "GladeXML") == 0) { + glade_xml = TRUE; + add_construct_glade($3, $4, NULL); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + | '(' TOKEN STRING STRING STRING ')' classflags { + if (strcmp ($2, "GladeXML") == 0) { + glade_xml = TRUE; + add_construct_glade($3, $4, $5); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + | '(' TOKEN TOKEN STRING ')' classflags { + if (strcmp ($2, "GladeXML") == 0) { + glade_xml = TRUE; + add_construct_glade($3, $4, NULL); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + | '(' TOKEN TOKEN STRING STRING ')' classflags { + if (strcmp ($2, "GladeXML") == 0) { + glade_xml = TRUE; + add_construct_glade($3, $4, $5); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + ; + classcode: classcode thing { ; } | thing { ; } ; thing: method { ; } + | TOKEN method { + if (strcmp ($1, "BonoboObject") != 0) { + g_free ($1); + yyerror (_("parse error")); + YYERROR; + } + g_free ($1); + last_added_method->bonobo_object_func = TRUE; + } + | TOKEN TYPETOKEN method { + if (strcmp ($1, "interface") != 0) { + g_free ($1); + g_free ($2); + yyerror (_("parse error")); + YYERROR; + } + g_free ($1); + node_set ((Node *)last_added_method, + "interface:steal", $2, + NULL); + } | variable { ; } | argument { ; } + | property { ; } | ';' { ; } ; @@ -387,29 +952,44 @@ scope: PUBLIC { the_scope = PUBLIC_SCOPE; } ; destructor: TOKEN TOKEN { - if(strcmp($1, "destroywith")==0) { - g_free($1); + if (strcmp ($1, "destroywith") == 0) { + g_free ($1); + destructor_unref = FALSE; + destructor = $2; + destructor_line = line_no; + destructor_simple = TRUE; + } else if (strcmp ($1, "unrefwith") == 0) { + g_free ($1); + destructor_unref = TRUE; destructor = $2; destructor_line = line_no; destructor_simple = TRUE; } else { - g_free($1); - g_free($2); - yyerror(_("parse error")); + g_free ($1); + g_free ($2); + yyerror (_("parse error")); YYERROR; } } | TOKEN '{' CCODE { - if(strcmp($1, "destroy")==0) { + if (strcmp ($1, "destroy") == 0) { g_free($1); + destructor_unref = FALSE; destructor = ($3)->str; g_string_free($3, FALSE); destructor_line = ccode_line; destructor_simple = FALSE; + } else if (strcmp ($1, "unref") == 0) { + g_free ($1); + destructor_unref = TRUE; + destructor = ($3)->str; + g_string_free ($3, FALSE); + destructor_line = ccode_line; + destructor_simple = FALSE; } else { - g_free($1); - g_string_free($3, TRUE); - yyerror(_("parse error")); + g_free ($1); + g_string_free ($3, TRUE); + yyerror (_("parse error")); YYERROR; } } @@ -431,6 +1011,14 @@ varoptions: destructor initializer { ; } | initializer destructor { ; } | initializer { destructor = NULL; } | destructor { initializer = NULL; } + | TOKEN { + if (strcmp ($1, "GladeXML") == 0) { + glade_widget = TRUE; + } else { + yyerror(_("parse error")); + YYERROR; + } + } | { destructor = NULL; initializer = NULL; @@ -444,82 +1032,144 @@ variable: scope type TOKEN varoptions ';' { push_variable($3, the_scope, $1, $4); } ; -argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { - if(strcmp($5,"get")==0 && - strcmp($8,"set")==0) { - Node *node; + +argument: ARGUMENT flags argtype TOKEN export TOKEN '{' CCODE TOKEN '{' CCODE ';' { + Node *node = NULL; + if(strcmp($6,"get")==0 && + strcmp($9,"set")==0) { Type *type = pop_type(); - g_free($5); g_free($8); - node = new_argument($3,type,$2,$4, - ($7)->str,$6, - ($10)->str,$9, - $1); - g_string_free($7,FALSE); - g_string_free($10,FALSE); + g_free ($6); + g_free ($9); + node = node_new (ARGUMENT_NODE, + "gtktype:steal", $3, + "atype:steal", type, + "flags:steal", $2, + "name:steal", $4, + "get:steal", ($8)->str, + "get_line", $7, + "set:steal", ($11)->str, + "set_line", $10, + "line_no", $1, + NULL); + class_nodes = g_list_append(class_nodes,node); - } else if(strcmp($5,"set")==0 && - strcmp($8,"get")==0) { - Node *node; + + g_string_free ($8, FALSE); + g_string_free ($11, FALSE); + + } else if(strcmp($6,"set")==0 && + strcmp($9,"get")==0) { Type *type = pop_type(); - g_free($5); g_free($8); - node = new_argument($3,type,$2,$4, - ($10)->str,$9, - ($7)->str,$6, - $1); - g_string_free($10,FALSE); - g_string_free($7,FALSE); + g_free ($6); + g_free ($9); + node = node_new (ARGUMENT_NODE, + "gtktype:steal", $3, + "atype:steal", type, + "flags:steal", $2, + "name:steal", $4, + "get:steal", ($11)->str, + "get_line", $10, + "set:steal", ($8)->str, + "set_line", $7, + "line_no", $1, + NULL); + g_string_free ($11, FALSE); + g_string_free ($8, FALSE); class_nodes = g_list_append(class_nodes,node); } else { - g_free($3); g_free($4); - g_free($5); g_free($8); - g_list_foreach($2,(GFunc)g_free,NULL); - g_string_free($10,TRUE); - g_string_free($7,TRUE); - yyerror(_("parse error")); + g_free ($3); + g_free ($4); + g_free ($6); + g_free ($9); + g_list_foreach ($2, (GFunc)g_free, NULL); + g_list_free ($2); + g_string_free ($11, TRUE); + g_string_free ($8, TRUE); + yyerror (_("parse error")); YYERROR; } + + if ($5 != NULL) { + Argument *arg = (Argument *)node; + export_accessors (arg->name, + arg->get != NULL, arg->get_line, + arg->set != NULL, arg->set_line, + arg->atype, + arg->gtktype, + arg->line_no); + g_free ($5); + } + } - | ARGUMENT flags argtype TOKEN TOKEN '{' CCODE ';' { - if(strcmp($5,"get")==0) { - Node *node; + | ARGUMENT flags argtype TOKEN export TOKEN '{' CCODE ';' { + Node *node = NULL; + if(strcmp($6, "get") == 0) { Type *type = pop_type(); - g_free($5); - node = new_argument($3,type,$2,$4, - ($7)->str,$6, - NULL,0, $1); - g_string_free($7,FALSE); - class_nodes = g_list_append(class_nodes,node); - } else if(strcmp($5,"set")==0) { - Node *node; + g_free ($6); + node = node_new (ARGUMENT_NODE, + "gtktype:steal", $3, + "atype:steal", type, + "flags:steal", $2, + "name:steal", $4, + "get:steal", ($8)->str, + "get_line", $7, + "line_no", $1, + NULL); + + g_string_free ($8, FALSE); + class_nodes = g_list_append(class_nodes, node); + } else if(strcmp($6, "set") == 0) { Type *type = pop_type(); - g_free($5); - node = new_argument($3,type,$2,$4, - NULL,0,($7)->str, - $6, $1); - g_string_free($7,FALSE); - class_nodes = g_list_append(class_nodes,node); + g_free ($6); + node = node_new (ARGUMENT_NODE, + "gtktype:steal", $3, + "atype:steal", type, + "flags:steal", $2, + "name:steal", $4, + "set:steal", ($8)->str, + "set_line", $7, + "line_no", $1, + NULL); + + g_string_free ($8, FALSE); + class_nodes = g_list_append (class_nodes, node); } else { - g_free($5); g_free($3); - g_free($4); - g_list_foreach($2,(GFunc)g_free,NULL); - g_string_free($7,TRUE); + g_free ($6); + g_free ($3); + g_free ($4); + g_list_foreach ($2, (GFunc)g_free, NULL); + g_list_free ($2); + g_string_free ($8, TRUE); yyerror(_("parse error")); YYERROR; } + + if ($5 != NULL) { + Argument *arg = (Argument *)node; + export_accessors (arg->name, + arg->get != NULL, arg->get_line, + arg->set != NULL, arg->set_line, + arg->atype, + arg->gtktype, + arg->line_no); + g_free ($5); + } } - | ARGUMENT flags argtype TOKEN TOKEN { + | ARGUMENT flags argtype TOKEN export TOKEN { Node *node; char *get, *set = NULL; Variable *var; Type *type; - char *root; + const char *root; - if(strcmp($5, "link")!=0 && - strcmp($5, "stringlink")!=0 && - strcmp($5, "objectlink")!=0) { - g_free($5); g_free($3); + if(strcmp($6, "link")!=0 && + strcmp($6, "stringlink")!=0 && + strcmp($6, "objectlink")!=0) { + g_free($6); + g_free($3); g_free($4); g_list_foreach($2,(GFunc)g_free,NULL); + g_list_free($2); yyerror(_("parse error")); YYERROR; } @@ -527,33 +1177,32 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { type = pop_type(); var = find_var_or_die($4, $1); - if(var->scope == PRIVATE_SCOPE) + if(var->scope == PRIVATE_SCOPE) { root = "self->_priv"; - else if(var->scope == CLASS_SCOPE) - root = "SELF_CLASS(GTK_OBJECT(self)->klass)"; - else + } else if(var->scope == CLASS_SCOPE) { + root = "SELF_GET_CLASS(self)"; + if(no_self_alias) + error_print(GOB_ERROR, $1, + _("Self aliases needed when autolinking to a classwide member")); + } else { root = "self"; + } - if(strcmp($5, "link")==0) { + if(strcmp($6, "link")==0) { set = g_strdup_printf("%s->%s = ARG;", root, $4); - } else if(strcmp($5, "stringlink")==0) { - set = g_strdup_printf("g_free(%s->%s); " - "%s->%s = g_strdup(ARG);", + } else if(strcmp($6, "stringlink")==0) { + set = g_strdup_printf("g_free (%s->%s); " + "%s->%s = g_strdup (ARG);", root, $4, root, $4); - } else if(strcmp($5, "objectlink")==0) { + } else if(strcmp($6, "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, $4, - root, $4, - root, $4, - root, $4, - root, $4, + "if (ARG != NULL) " + "g_object_ref (G_OBJECT (ARG)); " + "if (%s->%s != NULL) " + "g_object_unref (G_OBJECT (%s->%s)); " + "%s->%s = ARG;", root, $4, root, $4, root, $4); @@ -561,20 +1210,310 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { g_assert_not_reached(); } - /* get is the same for everything */ get = g_strdup_printf("ARG = %s->%s;", root, $4); + + g_free ($6); + + if (type == NULL) + type = (Type *)node_copy ((Node *)var->vtype); + + node = node_new (ARGUMENT_NODE, + "gtktype:steal", $3, + "atype:steal", type, + "flags:steal", $2, + "name:steal", $4, + "get:steal", get, + "get_line", $1, + "set:steal", set, + "set_line", $1, + "line_no", $1, + NULL); + + if ($5 != NULL) { + Argument *arg = (Argument *)node; + export_accessors (arg->name, + arg->get != NULL, arg->get_line, + arg->set != NULL, arg->set_line, + arg->atype, + arg->gtktype, + arg->line_no); + g_free ($5); + } + + class_nodes = g_list_append (class_nodes, node); + } + ; - g_free($5); +export: '(' TOKEN ')' { + if (strcmp ($2, "export")!=0) { + g_free ($2); + yyerror (_("parse error")); + YYERROR; + } + $$ = $2; + } + | { + $$ = NULL; + } + ; + +property: PROPERTY TOKEN TOKEN param_spec TOKEN '{' CCODE TOKEN '{' CCODE ';' { + ensure_property (); + node_set ((Node *)property, + "line_no", $1, + "gtktype:steal", debool ($2), + "name:steal", $3, + NULL); + if (strcmp ($5, "get") == 0 && + strcmp ($8, "set") == 0) { + node_set ((Node *)property, + "get:steal", ($7)->str, + "get_line", $6, + "set:steal", ($10)->str, + "set_line", $9, + NULL); + g_string_free ($7, FALSE); + g_string_free ($10, FALSE); + g_free ($5); + g_free ($8); + } else if (strcmp ($5, "set") == 0 && + strcmp ($8, "get") == 0) { + node_set ((Node *)property, + "get:steal", ($10)->str, + "get_line", $9, + "set:steal", ($7)->str, + "set_line", $6, + NULL); + g_string_free ($7, FALSE); + g_string_free ($10, FALSE); + g_free ($5); + g_free ($8); + } else { + g_string_free ($7, TRUE); + g_string_free ($10, TRUE); + g_free ($5); + g_free ($8); + node_free ((Node *)property); + property = NULL; + yyerror (_("parse error")); + YYERROR; + } + property_link_and_export ((Node *)property); + if (property != NULL) { + class_nodes = g_list_append (class_nodes, + property); + property = NULL; + } + } + | PROPERTY TOKEN TOKEN param_spec TOKEN '{' CCODE ';' { + ensure_property (); + node_set ((Node *)property, + "line_no", $1, + "gtktype:steal", debool ($2), + "name:steal", $3, + NULL); + if (strcmp ($5, "get") == 0) { + node_set ((Node *)property, + "get:steal", ($7)->str, + "get_line", $6, + NULL); + g_string_free ($7, FALSE); + g_free ($5); + } else if (strcmp ($5, "set") == 0) { + node_set ((Node *)property, + "set:steal", ($7)->str, + "set_line", $6, + NULL); + g_string_free ($7, FALSE); + g_free ($5); + } else { + g_string_free ($7, TRUE); + g_free ($5); + node_free ((Node *)property); + property = NULL; + yyerror (_("parse error")); + YYERROR; + } + property_link_and_export ((Node *)property); + if (property != NULL) { + class_nodes = g_list_append (class_nodes, + property); + property = NULL; + } + } + | PROPERTY TOKEN TOKEN param_spec ';' { + ensure_property (); + node_set ((Node *)property, + "line_no", $1, + "gtktype:steal", debool ($2), + "name:steal", $3, + NULL); + property_link_and_export ((Node *)property); + if (property != NULL) { + class_nodes = g_list_append (class_nodes, + property); + property = NULL; + } + } + ; +param_spec: '(' param_spec_list ')' { ; } + | { ; } + ; - if(!type) - type = copy_type(var->vtype); +param_spec_list: param_spec_list ',' param_spec_value { ; } + | param_spec_value { ; } + ; - node = new_argument($3, type, $2, - $4, get, $1, - set, $1, $1); - class_nodes = g_list_append(class_nodes,node); - } +string: STRING { $$ = $1; } + | TOKEN '(' STRING ')' { + if (strcmp ($1, "_") != 0) { + g_free ($1); + yyerror(_("parse error")); + YYERROR; + } + g_free ($1); + $$ = g_strconcat ("_(", $3, ")", NULL); + g_free ($3); + } + ; + +anyval: numtok { $$ = $1; } + | string { $$ = $1; } + ; + +param_spec_value: NAME '=' string { + ensure_property (); + node_set ((Node *)property, + "canonical_name:steal", gob_str_delete_quotes($3), + NULL); + } + | NICK '=' string { + ensure_property (); + node_set ((Node *)property, + "nick:steal", $3, + NULL); + } + | BLURB '=' string { + ensure_property (); + node_set ((Node *)property, + "blurb:steal", $3, + NULL); + } + | MAXIMUM '=' numtok { + ensure_property (); + node_set ((Node *)property, + "maximum:steal", $3, + NULL); + } + | MINIMUM '=' numtok { + ensure_property (); + node_set ((Node *)property, + "minimum:steal", $3, + NULL); + } + | DEFAULT_VALUE '=' anyval { + ensure_property (); + node_set ((Node *)property, + "default_value:steal", $3, + NULL); + } + | FLAGS '=' flaglist { + ensure_property (); + node_set ((Node *)property, + "flags:steal", $3, + NULL); + } + | TYPE '=' type { + Type *type = pop_type (); + ensure_property (); + node_set ((Node *)property, + "ptype:steal", type, + NULL); + } + | FLAGS_TYPE '=' TYPETOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | FLAGS_TYPE '=' TOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | ENUM_TYPE '=' TYPETOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | ENUM_TYPE '=' TOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | PARAM_TYPE '=' TYPETOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | PARAM_TYPE '=' TOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | BOXED_TYPE '=' TYPETOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | BOXED_TYPE '=' TOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | OBJECT_TYPE '=' TYPETOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | OBJECT_TYPE '=' TOKEN { + ensure_property (); + node_set ((Node *)property, + "extra_gtktype:steal", $3, + NULL); + } + | TOKEN { + ensure_property (); + if (strcmp ($1, "override") == 0) { + g_free($1); + node_set ((Node *)property, + "override", TRUE, + NULL); + } else if (strcmp ($1, "link") == 0) { + g_free($1); + node_set ((Node *)property, + "link", TRUE, + NULL); + } else if (strcmp ($1, "export") == 0) { + g_free($1); + node_set ((Node *)property, + "export", TRUE, + NULL); + } else { + g_free($1); + yyerror(_("parse error")); + YYERROR; + } + } ; argtype: TOKEN '(' TOKEN type ')' { @@ -584,10 +1523,10 @@ argtype: TOKEN '(' TOKEN type ')' { yyerror(_("parse error")); YYERROR; } - $$ = $1; + $$ = debool ($1); } | TOKEN { - $$ = $1; + $$ = debool ($1); typestack = g_list_prepend(typestack,NULL); } ; @@ -605,95 +1544,107 @@ flaglist: TOKEN '|' flaglist { ; -type: type1 { ; } - | CONST type1 { - Type *type = typestack->data; - char *oldname = type->name; - type->name = g_strconcat("const ",oldname,NULL); - g_free(oldname); - } - ; - -type1: type2 { - Node *node = new_type(0,$1,NULL); +type: specifier_list pointer { + Node *node = node_new (TYPE_NODE, + "name:steal", $1, + "pointer:steal", $2, + NULL); typestack = g_list_prepend(typestack,node); - } - | type2 stars { - Node *node = new_type(stars,$1,NULL); - stars = 0; + } + | specifier_list { + Node *node = node_new (TYPE_NODE, + "name:steal", $1, + NULL); typestack = g_list_prepend(typestack,node); - } + } ; -type2: UNSIGNED integer { - $$ = g_strconcat("unsigned ",$2,NULL); - } - | SIGNED integer { - $$ = g_strconcat("signed ",$2,NULL); - } - | integer { - $$ = g_strdup($1); - } - | UNSIGNED CHAR { - $$ = g_strdup("unsigned char"); - } - | SIGNED CHAR { - $$ = g_strdup("signed char"); - } - | CHAR { - $$ = g_strdup("char"); - } - | DOUBLE { - $$ = g_strdup("double"); - } - | FLOAT { - $$ = g_strdup("float"); - } - | TOKEN { +/* The special cases are neccessary to avoid conflicts */ +specifier_list: spec_list { $$ = $1; - } - | tspecifier TOKEN { - $$ = g_strconcat($1,$2,NULL); - g_free($2); - } - | TYPETOKEN { + } + | TOKEN { $$ = $1; - } - | VOID { - $$ = g_strdup("void"); - } + } + | CONST TOKEN { + $$ = g_strconcat("const ", $2, NULL); + g_free($2); + } + | TOKEN CONST { + $$ = g_strconcat($1, " const", NULL); + g_free($1); + } + | strunionenum TOKEN { + $$ = g_strconcat($1, " ", $2, NULL); + g_free($2); + } + | CONST strunionenum TOKEN { + $$ = g_strconcat("const ", $2, " ", + $3, NULL); + g_free($3); + } + | strunionenum TOKEN CONST { + $$ = g_strconcat($1, " ", + $2, " const", NULL); + g_free($2); + } ; -integer: LONG INT { - $$ = "long int"; - } - | LONG { - $$ = "long"; - } - | SHORT INT { - $$ = "short int"; - } - | SHORT { - $$ = "short"; - } - | INT { - $$ = "int"; - } +/* The special const cases take care of conflicts ! */ +spec_list: specifier spec_list { + $$ = g_strconcat($1, " ", $2, NULL); + g_free($2); + } + | TYPETOKEN spec_list { + $$ = g_strconcat($1, " ", $2, NULL); + g_free($1); + g_free($2); + } + | CONST spec_list { + $$ = g_strconcat("const ", $2, NULL); + g_free($2); + } + | TYPETOKEN { + $$ = $1; + } + | TYPETOKEN CONST { + $$ = g_strconcat($1, " const", NULL); + g_free($1); + } + | specifier { + $$ = g_strdup($1); + } + | specifier CONST { + $$ = g_strconcat($1, " const", NULL); + } ; - -tspecifier: ENUM { - $$ = "enum "; - } - | UNION { - $$ = "union "; - } - | STRUCT { - $$ = "struct "; - } + +specifier: VOID { $$ = "void"; } + | CHAR { $$ = "char"; } + | SHORT { $$ = "short"; } + | INT { $$ = "int"; } + | LONG { $$ = "long"; } + | FLOAT { $$ = "float"; } + | DOUBLE { $$ = "double"; } + | SIGNED { $$ = "signed"; } + | UNSIGNED { $$ = "unsigned"; } + ; + +strunionenum: STRUCT { $$ = "struct"; } + | UNION { $$ = "union"; } + | ENUM { $$ = "enum"; } ; - -stars: '*' stars { stars++; } - | '*' { stars++; } + +pointer: '*' { $$ = g_strdup("*"); } + | '*' CONST { $$ = g_strdup("* const"); } + | '*' pointer { + $$ = g_strconcat("*", $2, NULL); + g_free($2); + } + | '*' CONST pointer { + $$ = g_strconcat("* const", $3, NULL); + g_free($3); + } ; /* this never sets the_scope */ @@ -749,15 +1700,19 @@ fullsigtype: scope TOKEN sigtype { ; sigtype: TOKEN '(' tokenlist ')' { - gtktypes = g_list_prepend(gtktypes, $1); + gtktypes = g_list_prepend(gtktypes, debool ($1)); + } + | TOKEN STRING '(' tokenlist ')' { + gtktypes = g_list_prepend(gtktypes, debool ($1)); + signal_name=$2; } ; tokenlist: tokenlist ',' TOKEN { - gtktypes = g_list_append(gtktypes, $3); + gtktypes = g_list_append(gtktypes, debool ($3)); } | TOKEN { - gtktypes = g_list_append(gtktypes, $1); + gtktypes = g_list_append(gtktypes, debool ($1)); } ; @@ -766,7 +1721,7 @@ codenocode: '{' CCODE { $$ = $2; } ; /*here CCODE will include the ending '}' */ -method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenocode { +method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' methodmods codenocode { if(!has_self) { yyerror(_("signal without 'self' as " "first parameter")); @@ -778,11 +1733,18 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc free_all_global_state(); YYERROR; } + if (funcattrs != NULL) { + char *error = g_strdup_printf + (_("function attribute macros ('%s' in this case) may not be used with signal methods"), + funcattrs); + yyerror (error); + YYERROR; + } push_function(the_scope, $3,NULL, $5, $10,$1, ccode_line, vararg, $2); } - | scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' returnvals codenocode { + | scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' methodmods codenocode { if(!has_self) { yyerror(_("signal without 'self' as " "first parameter")); @@ -794,11 +1756,18 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc free_all_global_state(); YYERROR; } + if (funcattrs != NULL) { + char *error = g_strdup_printf + (_("function attribute macros ('%s' in this case) may not be used with signal methods"), + funcattrs); + yyerror (error); + YYERROR; + } push_function(the_scope, $4, NULL, $6, $11, $2, ccode_line, vararg, $3); } - | VIRTUAL scope type TOKEN '(' funcargs ')' returnvals codenocode { + | VIRTUAL scope type TOKEN '(' funcargs ')' methodmods codenocode { if(!has_self) { yyerror(_("virtual method without 'self' as " "first parameter")); @@ -810,11 +1779,18 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc free_all_global_state(); YYERROR; } + if (funcattrs != NULL) { + char *error = g_strdup_printf + (_("function attribute macros ('%s' in this case) may not be used with virtual methods"), + funcattrs); + yyerror (error); + YYERROR; + } push_function(the_scope, VIRTUAL_METHOD, NULL, $4, $9, $1, ccode_line, vararg, NULL); } - | scope VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { + | scope VIRTUAL type TOKEN '(' funcargs ')' methodmods codenocode { if(!has_self) { yyerror(_("virtual method without 'self' as " "first parameter")); @@ -826,28 +1802,49 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc free_all_global_state(); YYERROR; } + if (funcattrs != NULL) { + char *error = g_strdup_printf + (_("function attribute macros ('%s' in this case) may not be used with virtual methods"), + funcattrs); + yyerror (error); + YYERROR; + } push_function(the_scope, VIRTUAL_METHOD, NULL, $4, $9, $2, ccode_line, vararg, NULL); } - | VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { + | VIRTUAL type TOKEN '(' funcargs ')' methodmods codenocode { if(!has_self) { - yyerror(_("virtual method without 'self' as " + yyerror(_("virtual method without 'szelf' as " "first parameter")); free_all_global_state(); YYERROR; } + if (funcattrs != NULL) { + char *error = g_strdup_printf + (_("function attribute macros ('%s' in this case) may not be used with virtual methods"), + funcattrs); + yyerror (error); + YYERROR; + } push_function(PUBLIC_SCOPE, VIRTUAL_METHOD, NULL, $3, $8, $1, ccode_line, vararg, NULL); } - | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' returnvals codenocode { + | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' methodmods codenocode { + if (funcattrs != NULL) { + char *error = g_strdup_printf + (_("function attribute macros ('%s' in this case) may not be used with override methods"), + funcattrs); + yyerror (error); + YYERROR; + } push_function(NO_SCOPE, OVERRIDE_METHOD, $3, $6, $11, $1, ccode_line, vararg, NULL); } - | scope type TOKEN '(' funcargs ')' returnvals codenocode { + | scope type TOKEN '(' funcargs ')' methodmods codenocode { if(the_scope == CLASS_SCOPE) { yyerror(_("a method cannot be of class scope")); free_all_global_state(); @@ -868,20 +1865,40 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc push_function(NO_SCOPE, CLASS_INIT_METHOD, NULL, $1, $5, $2, ccode_line, FALSE, NULL); + } else if(strcmp($1, "constructor")==0) { + push_init_arg($3, FALSE); + push_function(NO_SCOPE, CONSTRUCTOR_METHOD, NULL, + $1, $5, $2, + ccode_line, FALSE, NULL); + } else if(strcmp($1, "dispose")==0) { + push_init_arg($3, FALSE); + push_function(NO_SCOPE, DISPOSE_METHOD, NULL, + $1, $5, $2, + ccode_line, FALSE, NULL); + } else if(strcmp($1, "finalize")==0) { + push_init_arg($3, FALSE); + push_function(NO_SCOPE, FINALIZE_METHOD, NULL, + $1, $5, $2, + ccode_line, FALSE, NULL); + } else { g_free($1); g_free($3); - g_string_free($3,TRUE); - yyerror(_("parse error")); + g_string_free($5,TRUE); + yyerror(_("parse error " + "(untyped blocks must be init, " + "class_init, constructor, dispose " + "or finalize)")); YYERROR; } } ; -returnvals: TOKEN retcode { +methodmods: TOKEN retcode { + g_free(funcattrs); funcattrs = NULL; g_free(onerror); onerror = NULL; g_free(defreturn); defreturn = NULL; - if(!set_return_value($1, $2)) { + if(!set_attr_value($1, $2)) { g_free($1); g_free($2); yyerror(_("parse error")); @@ -890,16 +1907,17 @@ returnvals: TOKEN retcode { g_free($1); } | TOKEN retcode TOKEN retcode { + g_free(funcattrs); funcattrs = NULL; g_free(onerror); onerror = NULL; g_free(defreturn); defreturn = NULL; - if(!set_return_value($1, $2)) { + if(!set_attr_value($1, $2)) { g_free($1); g_free($2); g_free($3); g_free($4); yyerror(_("parse error")); YYERROR; } - if(!set_return_value($3, $4)) { - onerror = defreturn = NULL; + if(!set_attr_value($3, $4)) { + funcattrs = onerror = defreturn = NULL; g_free($1); g_free($2); g_free($3); g_free($4); yyerror(_("parse error")); @@ -908,7 +1926,39 @@ returnvals: TOKEN retcode { g_free($1); g_free($3); } + | TOKEN retcode TOKEN retcode TOKEN retcode { + g_free(funcattrs); funcattrs = NULL; + g_free(onerror); onerror = NULL; + g_free(defreturn); defreturn = NULL; + if(!set_attr_value($1, $2)) { + g_free($1); g_free($2); + g_free($3); g_free($4); + g_free($5); g_free($6); + yyerror(_("parse error")); + YYERROR; + } + if(!set_attr_value($3, $4)) { + funcattrs = onerror = defreturn = NULL; + g_free($1); g_free($2); + g_free($3); g_free($4); + g_free($5); g_free($6); + yyerror(_("parse error")); + YYERROR; + } + if(!set_attr_value($5, $6)) { + funcattrs = onerror = defreturn = NULL; + g_free($1); g_free($2); + g_free($3); g_free($4); + g_free($5); g_free($6); + yyerror(_("parse error")); + YYERROR; + } + g_free($1); + g_free($3); + g_free($5); + } | { + g_free(funcattrs); funcattrs = NULL; g_free(onerror); onerror = NULL; g_free(defreturn); defreturn = NULL; } @@ -916,8 +1966,8 @@ returnvals: TOKEN retcode { retcode: numtok { $$ = $1; } | '{' CCODE { - $$ = ($3)->str; - g_string_free($3, FALSE); + $$ = ($2)->str; + g_string_free($2, FALSE); } ; @@ -926,23 +1976,65 @@ funcargs: VOID { vararg = FALSE; has_self = FALSE; } vararg = FALSE; has_self = TRUE; if(strcmp($1,"self")==0) - push_self($1); + push_self($1, FALSE); else { g_free($1); yyerror(_("parse error")); YYERROR; } } + | TOKEN CONST { + vararg = FALSE; + has_self = TRUE; + if(strcmp($1,"self")==0) + push_self($1, TRUE); + else { + g_free($1); + yyerror(_("parse error")); + YYERROR; + } + } + | CONST TOKEN { + vararg = FALSE; + has_self = TRUE; + if(strcmp($2,"self")==0) + push_self($2, TRUE); + else { + g_free($2); + yyerror(_("parse error")); + YYERROR; + } + } | TOKEN ',' arglist { has_self = TRUE; if(strcmp($1,"self")==0) - push_self($1); + push_self($1, FALSE); + else { + g_free($1); + yyerror(_("parse error")); + YYERROR; + } + } + | TOKEN CONST ',' arglist { + has_self = TRUE; + if(strcmp($1,"self")==0) + push_self($1, TRUE); else { g_free($1); yyerror(_("parse error")); YYERROR; } } + | CONST TOKEN ',' arglist { + has_self = TRUE; + if(strcmp($2,"self")==0) + push_self($2, TRUE); + else { + g_free($2); + yyerror(_("parse error")); + YYERROR; + } + } | arglist { has_self = FALSE; } ; @@ -984,10 +2076,14 @@ checklist: checklist check { ; } check: TOKEN { if(strcmp($1,"type")==0) { - Node *node = new_check(TYPE_CHECK,NULL); + Node *node = node_new (CHECK_NODE, + "chtype", TYPE_CHECK, + NULL); checks = g_list_append(checks,node); } else if(strcmp($1,"null")==0) { - Node *node = new_check(NULL_CHECK,NULL); + Node *node = node_new (CHECK_NODE, + "chtype", NULL_CHECK, + NULL); checks = g_list_append(checks,node); } else { yyerror(_("parse error")); @@ -996,36 +2092,166 @@ check: TOKEN { g_free($1); } | '>' numtok { - Node *node = new_check(GT_CHECK,$2); + Node *node = node_new (CHECK_NODE, + "chtype", GT_CHECK, + "number:steal", $2, + NULL); checks = g_list_append(checks,node); } | '<' numtok { - Node *node = new_check(LT_CHECK,$2); + Node *node = node_new (CHECK_NODE, + "chtype", LT_CHECK, + "number:steal", $2, + NULL); checks = g_list_append(checks,node); } | '>' '=' numtok { - Node *node = new_check(GE_CHECK,$3); + Node *node = node_new (CHECK_NODE, + "chtype", GE_CHECK, + "number:steal", $3, + NULL); checks = g_list_append(checks,node); } | '<' '=' numtok { - Node *node = new_check(LE_CHECK,$3); + Node *node = node_new (CHECK_NODE, + "chtype", LE_CHECK, + "number:steal", $3, + NULL); checks = g_list_append(checks,node); } | '=' '=' numtok { - Node *node = new_check(EQ_CHECK,$3); + Node *node = node_new (CHECK_NODE, + "chtype", EQ_CHECK, + "number:steal", $3, + NULL); checks = g_list_append(checks,node); } | '!' '=' numtok { - Node *node = new_check(NE_CHECK,$3); + Node *node = node_new (CHECK_NODE, + "chtype", NE_CHECK, + "number:steal", $3, + NULL); checks = g_list_append(checks,node); } ; - + +enumcode: ENUM TOKEN '{' enumvals '}' TYPETOKEN ';' { + Node *node = node_new (ENUMDEF_NODE, + "etype:steal", $6, + "prefix:steal", $2, + "values:steal", enum_vals, + NULL); + enum_vals = NULL; + nodes = g_list_append (nodes, node); + } + | ENUM TOKEN '{' enumvals ',' '}' TYPETOKEN ';' { + Node *node = node_new (ENUMDEF_NODE, + "etype:steal", $7, + "prefix:steal", $2, + "values:steal", enum_vals, + NULL); + enum_vals = NULL; + nodes = g_list_append (nodes, node); + } + ; + +enumvals: enumvals ',' enumval {;} + | enumval {;} + ; + +enumval: TOKEN '=' numtok { + Node *node; + char *num = $3; + + /* A float value, that's a bad enum */ + if (num[0] >= '0' && + num[0] <= '9' && + strchr (num, '.') != NULL) { + g_free ($1); + g_free (num); + yyerror(_("parse error (enumerator value not integer constant)")); + YYERROR; + } + + node = node_new (ENUMVALUE_NODE, + "name:steal", $1, + "value:steal", num, + NULL); + enum_vals = g_list_append (enum_vals, node); + } + | TOKEN { + Node *node; + + node = node_new (ENUMVALUE_NODE, + "name:steal", $1, + NULL); + enum_vals = g_list_append (enum_vals, node); + } + ; + +flagcode: FLAGS TOKEN '{' flagvals '}' TYPETOKEN ';' { + Node *node = node_new (FLAGS_NODE, + "ftype:steal", $6, + "prefix:steal", $2, + "values:steal", flag_vals, + NULL); + flag_vals = NULL; + nodes = g_list_append (nodes, node); + } + | FLAGS TOKEN '{' flagvals ',' '}' TYPETOKEN ';' { + Node *node = node_new (FLAGS_NODE, + "ftype:steal", $7, + "prefix:steal", $2, + "values:steal", flag_vals, + NULL); + flag_vals = NULL; + nodes = g_list_append (nodes, node); + } + ; + +flagvals: flagvals ',' TOKEN { + flag_vals = g_list_append (flag_vals, $3); + } + | TOKEN { + flag_vals = g_list_append (flag_vals, $1); + } + ; + +errorcode: ERROR TOKEN '{' errorvals '}' TYPETOKEN ';' { + Node *node = node_new (ERROR_NODE, + "etype:steal", $6, + "prefix:steal", $2, + "values:steal", error_vals, + NULL); + error_vals = NULL; + nodes = g_list_append (nodes, node); + } + | ERROR TOKEN '{' errorvals ',' '}' TYPETOKEN ';' { + Node *node = node_new (ERROR_NODE, + "etype:steal", $7, + "prefix:steal", $2, + "values:steal", error_vals, + NULL); + error_vals = NULL; + nodes = g_list_append (nodes, node); + } + ; + +errorvals: errorvals ',' TOKEN { + error_vals = g_list_append (error_vals, $3); + } + | TOKEN { + error_vals = g_list_append (error_vals, $1); + } + ; + + numtok: NUMBER { $$ = $1; } | '-' NUMBER { $$ = g_strconcat("-",$2,NULL); g_free($2); } + | SINGLE_CHAR { $$ = $1; } | TOKEN { $$ = $1; } ;