From 1301fe7a8fe89ca97e5133ba9ba7dabdf74b51bf Mon Sep 17 00:00:00 2001 From: "zik.saleeba" Date: Tue, 27 Jul 2010 18:16:05 +0000 Subject: [PATCH] More intelligent allocation/deallocation of parser data. It should now be possible to report error messages from previously-parsed files. git-svn-id: http://picoc.googlecode.com/svn/trunk@480 21eae674-98b7-11dd-bd71-f92a316d2d60 --- include.c | 2 +- parse.c | 57 +++++++++++++++++++++++++++++++--------- picoc.c | 8 +++--- picoc.h | 2 +- platform/platform_unix.c | 15 +---------- 5 files changed, 52 insertions(+), 32 deletions(-) diff --git a/include.c b/include.c index 4f80ce1..6b9d286 100644 --- a/include.c +++ b/include.c @@ -87,7 +87,7 @@ void IncludeFile(char *FileName) /* parse the setup C source code - may define types etc. */ if (LInclude->SetupCSource != NULL) - Parse(FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE); + Parse(FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE, TRUE, FALSE); /* set up the library functions */ if (LInclude->FuncList != NULL) diff --git a/parse.c b/parse.c index 19c0069..b02e843 100644 --- a/parse.c +++ b/parse.c @@ -1,13 +1,30 @@ #include "picoc.h" -/* a chunk of heap-allocated tokens we should cleanup when we're done */ -static void *CleanupTokens = NULL; +/* a chunk of heap-allocated tokens we'll cleanup when we're done */ +struct CleanupTokenNode +{ + void *Tokens; + const char *SourceText; + struct CleanupTokenNode *Next; +}; + +static struct CleanupTokenNode *CleanupTokenList = NULL; + /* deallocate any memory */ void ParseCleanup() { - if (CleanupTokens != NULL) - HeapFreeMem(CleanupTokens); + while (CleanupTokenList != NULL) + { + struct CleanupTokenNode *Next = CleanupTokenList->Next; + + HeapFreeMem(CleanupTokenList->Tokens); + if (CleanupTokenList->SourceText != NULL) + HeapFreeMem((void *)CleanupTokenList->SourceText); + + HeapFreeMem(CleanupTokenList); + CleanupTokenList = Next; + } } /* parse a statement, but only run it if Condition is TRUE */ @@ -725,16 +742,32 @@ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemi } /* quick scan a source file for definitions */ -void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt) +void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource) { struct ParseState Parser; enum ParseResult Ok; + struct CleanupTokenNode *NewCleanupNode; - void *OldCleanupTokens = CleanupTokens; void *Tokens = LexAnalyse(FileName, Source, SourceLen, NULL); - if (OldCleanupTokens == NULL) - CleanupTokens = Tokens; - + + /* allocate a cleanup node so we can clean up the tokens later */ + if (!CleanupNow) + { + NewCleanupNode = HeapAllocMem(sizeof(struct CleanupTokenNode)); + if (NewCleanupNode == NULL) + ProgramFail(NULL, "out of memory"); + + NewCleanupNode->Tokens = Tokens; + if (CleanupSource) + NewCleanupNode->SourceText = Source; + else + NewCleanupNode->SourceText = NULL; + + NewCleanupNode->Next = CleanupTokenList; + CleanupTokenList = NewCleanupNode; + } + + /* do the parsing */ LexInitParser(&Parser, Source, Tokens, FileName, RunIt); do { @@ -744,9 +777,9 @@ void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt) if (Ok == ParseResultError) ProgramFail(&Parser, "parse error"); - HeapFreeMem(Tokens); - if (OldCleanupTokens == NULL) - CleanupTokens = NULL; + /* clean up */ + if (CleanupNow) + HeapFreeMem(Tokens); } /* parse interactively */ diff --git a/picoc.c b/picoc.c index b67f112..65ee392 100644 --- a/picoc.c +++ b/picoc.c @@ -59,18 +59,18 @@ void CallMain(int argc, char **argv) if (FuncValue->Val->FuncDef.ReturnType == &VoidType) { if (FuncValue->Val->FuncDef.NumParams == 0) - Parse("", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE); + Parse("startup", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE, TRUE, FALSE); else - Parse("", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE); + Parse("startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE, TRUE, FALSE); } else { VariableDefinePlatformVar(NULL, "__exit_value", &IntType, (union AnyValue *)&ExitValue, TRUE); if (FuncValue->Val->FuncDef.NumParams == 0) - Parse("", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE); + Parse("startup", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE, TRUE, FALSE); else - Parse("", CALL_MAIN_WITH_ARGS_RETURN_INT, strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), TRUE); + Parse("startup", CALL_MAIN_WITH_ARGS_RETURN_INT, strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), TRUE, TRUE, FALSE); } } diff --git a/picoc.h b/picoc.h index efa5244..1ee80e4 100644 --- a/picoc.h +++ b/picoc.h @@ -342,7 +342,7 @@ void LexInteractiveStatementPrompt(); /* parse.c */ enum ParseResult ParseStatement(struct ParseState *Parser, int CheckTrailingSemicolon); struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueType *ReturnType, char *Identifier); -void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt); +void Parse(const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource); void ParseInteractive(); void ParseCleanup(); void ParserCopyPos(struct ParseState *To, struct ParseState *From); diff --git a/platform/platform_unix.c b/platform/platform_unix.c index 9654f34..fc86be3 100644 --- a/platform/platform_unix.c +++ b/platform/platform_unix.c @@ -5,14 +5,8 @@ #include #endif -/* a source file we need to clean up */ -static char *CleanupText = NULL; - -/* deallocate any storage */ void PlatformCleanup() { - if (CleanupText != NULL) - free(CleanupText); } /* get a line of interactive input */ @@ -91,15 +85,8 @@ char *PlatformReadFile(const char *FileName) void PlatformScanFile(const char *FileName) { char *SourceStr = PlatformReadFile(FileName); - char *OrigCleanupText = CleanupText; - if (CleanupText == NULL) - CleanupText = SourceStr; - Parse(FileName, SourceStr, strlen(SourceStr), TRUE); - free(SourceStr); - - if (OrigCleanupText == NULL) - CleanupText = NULL; + Parse(FileName, SourceStr, strlen(SourceStr), TRUE, FALSE, TRUE); } /* mark where to end the program for platforms which require this */