X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/509cf0693fc440c71bdd3e71ea8947a6b4eb0bcf..853c670e4b839fd435507201f04d16080590a894:/src/parse.y diff --git a/src/parse.y b/src/parse.y index f052991..ba4615b 100644 --- a/src/parse.y +++ b/src/parse.y @@ -23,6 +23,7 @@ #include "config.h" #include #include +#include #include #include "treefuncs.h" @@ -35,9 +36,9 @@ GList *nodes = NULL; static GList *class_nodes = NULL; Node *class = NULL; +char *chunk_size = NULL; static GList *typestack = NULL; -static int stars = 0; static GList *funcargs = NULL; static GList *checks = NULL; static int has_self = FALSE; @@ -126,10 +127,10 @@ 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) { + type = (Type *)new_type(g_strdup("void"), NULL, 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 +141,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")); } } } @@ -191,6 +192,9 @@ free_all_global_state(void) 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; @@ -225,18 +229,19 @@ push_init_arg(char *name, int is_class) else tn = g_strdup(((Class *)class)->otype); - type = new_type(1,tn,NULL); + type = new_type(tn, g_strdup("*"), NULL); node = new_funcarg((Type *)type,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); + type = new_type(g_strdup(((Class *)class)->otype), + g_strdup(constant ? "const *" : "*"), 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); @@ -247,7 +252,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,8 +263,7 @@ 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; @@ -365,11 +368,31 @@ class: classdec '{' classcode '}' { } ; -classdec: CLASS TYPETOKEN FROM TYPETOKEN { - class = new_class($2,$4,NULL); +classdec: CLASS TYPETOKEN FROM TYPETOKEN chunk { + class = new_class($2,$4,chunk_size,NULL); } ; - + +chunk: + | '(' TOKEN TOKEN ')' { + if(strcmp($2,"chunks") == 0) { + chunk_size = g_strdup($4); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + | '(' TOKEN NUMBER ')' { + if(strcmp($2,"chunks") == 0) { + if(atoi($4) != 0) + chunk_size = g_strdup($4); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + ; + classcode: classcode thing { ; } | thing { ; } ; @@ -473,6 +496,7 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { g_free($3); g_free($4); g_free($5); g_free($8); g_list_foreach($2,(GFunc)g_free,NULL); + g_list_free($2); g_string_free($10,TRUE); g_string_free($7,TRUE); yyerror(_("parse error")); @@ -480,29 +504,30 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { } } | ARGUMENT flags argtype TOKEN TOKEN '{' CCODE ';' { - if(strcmp($5,"get")==0) { + if(strcmp($5, "get") == 0) { Node *node; 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 = 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; Type *type = pop_type(); g_free($5); - node = new_argument($3,type,$2,$4, - NULL,0,($7)->str, + 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_string_free($7, 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_list_foreach($2, (GFunc)g_free, NULL); + g_list_free($2); + g_string_free($7, TRUE); yyerror(_("parse error")); YYERROR; } @@ -520,6 +545,7 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { g_free($5); g_free($3); g_free($4); g_list_foreach($2,(GFunc)g_free,NULL); + g_list_free($2); yyerror(_("parse error")); YYERROR; } @@ -529,9 +555,12 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { var = find_var_or_die($4, $1); 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) { @@ -553,16 +582,16 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { root, $4, root, $4, root, $4, - root, $4, - root, $4, - root, $4, root, $4); } else { g_assert_not_reached(); } - /* get is the same for everything */ - get = g_strdup_printf("ARG = %s->%s;", root, $4); + if(strcmp($5, "stringlink")==0) { + get = g_strdup_printf("ARG = g_strdup(%s->%s);", root, $4); + } else + /* For everything else, get is just straight assignment */ + get = g_strdup_printf("ARG = %s->%s;", root, $4); g_free($5); @@ -605,95 +634,102 @@ 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 = new_type($1, $2, NULL); typestack = g_list_prepend(typestack,node); - } - | type2 stars { - Node *node = new_type(stars,$1,NULL); - stars = 0; + } + | specifier_list { + Node *node = new_type($1, NULL, 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 */ @@ -928,23 +964,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; } ;