X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/072bb12e618b26cce359784aa56f9a2b70e1ce52..486240dc4c5d57b0afaddba60d87fe375112bed5:/src/parse.y diff --git a/src/parse.y b/src/parse.y index f052991..9764b67 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 @@ -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,7 +229,7 @@ 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); } @@ -236,7 +240,7 @@ push_self(char *id) 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("*"), 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); @@ -365,11 +369,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 { ; } ; @@ -553,16 +577,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 +629,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 */