diff --git a/src/level_parser.y b/src/level_parser.y index 72a19f183..f6821c9a3 100644 --- a/src/level_parser.y +++ b/src/level_parser.y @@ -43,6 +43,21 @@ void yyerror(const char* msg) debug(LOG_ERROR, "Level File parse error: `%s` at line `%d` text `%s`", msg, levGetErrorLine(), levGetErrorText()); } +static void freeDataSet(LEVEL_DATASET * const d) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(d->apDataFiles); ++i) + { + if (d->apDataFiles[i] != NULL) + { + free(d->apDataFiles[i]); + } + } + + free(d->pName); + free(d); +} + #define YYPARSE_PARAM yyparse_param #define yycontext ((parser_context*)yyparse_param) @@ -63,7 +78,18 @@ void yyerror(const char* msg) %token QTEXT %token INTEGER -%destructor { free($$); } IDENTIFIER QTEXT +%destructor { + // Force type checking by the compiler + char * const s = $$; + + if (s != NULL) + free(s); +} IDENTIFIER QTEXT + +%destructor { + if ($$ != NULL) + freeDataSet($$); +} level_line level_rule /* keywords */ %token LEVEL @@ -83,7 +109,7 @@ void yyerror(const char* msg) %token MISS_CLEAR /* rule types */ -%type level_rule +%type level_line level_rule %type level_type %start lev_file @@ -99,6 +125,9 @@ lev_file: /* Empty to allow empty files */ ; level_entry: level_line level_directives_1st dataload_directives + { + LIST_ADDEND(psLevels, $1, LEVEL_DATASET); + } ; level_line: level_rule IDENTIFIER @@ -111,12 +140,16 @@ level_line: level_rule IDENTIFIER if (psFoundData == NULL) { yyerror("Cannot find full data set for `camchange'"); + freeDataSet($1); + free($2); YYABORT; } if (psFoundData->type != LDS_CAMSTART) { yyerror("Invalid data set name for `camchange'"); + freeDataSet($1); + free($2); YYABORT; } psFoundData->psChange = $1; @@ -127,6 +160,7 @@ level_line: level_rule IDENTIFIER // Make this dataset current to our parsing context yycontext->dataset = $1; + $$ = $1; } ; @@ -145,7 +179,6 @@ level_rule: level_type $$->game = -1; $$->dataDir = yycontext->datadir; - LIST_ADDEND(psLevels, $$, LEVEL_DATASET); yycontext->currData = 0; yycontext->dataLoaded = false;