When parsing and compiling a script, return the length in an output parameter instead so the method can return a boolean to indicate success.

This fixes #221 where a script with no code would fail.
This commit is contained in:
smallmodel 2024-04-08 21:00:48 +02:00
parent 9eec50d69f
commit e3beec985e
No known key found for this signature in database
GPG key ID: 9F2D623CEDF08512
3 changed files with 41 additions and 32 deletions

View file

@ -104,7 +104,7 @@ void AbstractScript::PrintSourcePos(sourceinfo_t *sourcePos, bool dev)
if (GetSourceAt(sourcePos->sourcePos, &sourceLine, column, line)) {
PrintSourcePos(sourceLine, column, line, dev);
} else {
glbs.DPrintf(
gi.DPrintf(
"file '%s', source pos %d line %d column %d:\n",
Filename().c_str(),
sourcePos->sourcePos,
@ -123,7 +123,7 @@ void AbstractScript::PrintSourcePos(size_t sourcePos, bool dev)
if (GetSourceAt(sourcePos, &sourceLine, column, line)) {
PrintSourcePos(sourceLine, column, line, dev);
} else {
glbs.DPrintf("file '%s', source pos %d:\n", Filename().c_str(), sourcePos);
gi.DPrintf("file '%s', source pos %d:\n", Filename().c_str(), sourcePos);
}
}
@ -153,7 +153,7 @@ void AbstractScript::PrintSourcePos(str sourceLine, int column, int line, bool d
markerLine.append("^");
glbs.DPrintf("(%s, %d):\n%s\n%s\n", Filename().c_str(), line, sourceLine.c_str(), markerLine.c_str());
gi.DPrintf("(%s, %d):\n%s\n%s\n", Filename().c_str(), line, sourceLine.c_str(), markerLine.c_str());
}
AbstractScript::AbstractScript()
@ -493,7 +493,7 @@ void GameScript::Archive(Archiver& arc)
}
else
{
m_ProgBuffer = ( unsigned char * )glbs.Malloc( m_ProgLength );
m_ProgBuffer = ( unsigned char * )gi.Malloc( m_ProgLength );
code_pos = m_ProgBuffer;
code_end = m_ProgBuffer + m_ProgLength;
@ -591,14 +591,14 @@ void GameScript::Archive(Archiver& arc)
{
fileHandle_t filehandle = NULL;
m_SourceLength = glbs.FS_ReadFile( Filename().c_str(), ( void ** )&m_SourceBuffer, true );
m_SourceLength = gi.FS_ReadFile( Filename().c_str(), ( void ** )&m_SourceBuffer, true );
if( m_SourceLength > 0 )
{
m_SourceBuffer = ( char * )glbs.Malloc( m_SourceLength );
m_SourceBuffer = ( char * )gi.Malloc( m_SourceLength );
glbs.FS_Read( m_SourceBuffer, m_SourceLength, filehandle );
glbs.FS_FCloseFile( filehandle );
gi.FS_Read( m_SourceBuffer, m_SourceLength, filehandle );
gi.FS_FCloseFile( filehandle );
}
}
@ -661,12 +661,12 @@ void GameScript::Close(void)
}
if (m_ProgBuffer) {
glbs.Free(m_ProgBuffer);
gi.Free(m_ProgBuffer);
m_ProgBuffer = NULL;
}
if (m_SourceBuffer) {
glbs.Free(m_SourceBuffer);
gi.Free(m_SourceBuffer);
m_SourceBuffer = NULL;
}
@ -680,7 +680,7 @@ void GameScript::Load(const void *sourceBuffer, size_t sourceLength)
size_t nodeLength;
char *m_PreprocessedBuffer;
m_SourceBuffer = (char *)glbs.Malloc(sourceLength + 2);
m_SourceBuffer = (char *)gi.Malloc(sourceLength + 2);
m_SourceLength = sourceLength;
// Original mohaa doesn't reallocate the input string to append a newline
@ -694,19 +694,24 @@ void GameScript::Load(const void *sourceBuffer, size_t sourceLength)
Compiler.Reset();
m_PreprocessedBuffer = Compiler.Preprocess(m_SourceBuffer);
nodeLength = Compiler.Parse(this, m_PreprocessedBuffer, "script");
Compiler.Preclean(m_PreprocessedBuffer);
if (!nodeLength) {
glbs.DPrintf2("^~^~^ Script file compile error: Couldn't parse '%s'\n", Filename().c_str());
if (!Compiler.Parse(this, m_PreprocessedBuffer, "script", nodeLength)) {
gi.DPrintf2("^~^~^ Script file compile error: Couldn't parse '%s'\n", Filename().c_str());
return Close();
}
m_ProgBuffer = (unsigned char *)glbs.Malloc(nodeLength);
m_ProgLength = Compiler.Compile(this, m_ProgBuffer);
if (nodeLength == 0) {
// No code, assume success
requiredStackSize = 0;
successCompile = true;
return;
}
if (!m_ProgLength) {
glbs.DPrintf2("^~^~^ Script file compile error: Couldn't compile '%s'\n", Filename().c_str());
Compiler.Preclean(m_PreprocessedBuffer);
m_ProgBuffer = (unsigned char *)gi.Malloc(nodeLength);
if (!Compiler.Compile(this, m_ProgBuffer, m_ProgLength)) {
gi.DPrintf2("^~^~^ Script file compile error: Couldn't compile '%s'\n", Filename().c_str());
return Close();
}

View file

@ -1497,7 +1497,7 @@ int yyerror(const char *msg)
return 1;
}
size_t ScriptCompiler::Parse(GameScript *gameScript, char *sourceBuffer, const char *type)
bool ScriptCompiler::Parse(GameScript *gameScript, char *sourceBuffer, const char *type, size_t& outLength)
{
parsedata = yyparsedata();
@ -1515,6 +1515,8 @@ size_t ScriptCompiler::Parse(GameScript *gameScript, char *sourceBuffer, const c
script = gameScript;
stateScript = &gameScript->m_State;
outLength = 0;
yy_init_script();
parsetree_init();
@ -1531,22 +1533,23 @@ size_t ScriptCompiler::Parse(GameScript *gameScript, char *sourceBuffer, const c
}
yylex_destroy();
return 0;
return false;
}
} catch (ScriptException& exc) {
yylex_destroy();
exc;
return 0;
return false;
}
yylex_destroy();
return parsedata.total_length;
outLength = parsedata.total_length;
return true;
}
size_t ScriptCompiler::Compile(GameScript *gameScript, unsigned char *progBuffer)
bool ScriptCompiler::Compile(GameScript *gameScript, unsigned char *progBuffer, size_t& outLength)
{
size_t length;
bool success = false;
if (progBuffer == NULL) {
glbs.DPrintf("Invalid program buffer\n");
@ -1570,21 +1573,22 @@ size_t ScriptCompiler::Compile(GameScript *gameScript, unsigned char *progBuffer
if (compileSuccess) {
stateScript->AddLabel("", code_ptr);
length = code_pos - code_ptr;
outLength = code_pos - code_ptr;
success = true;
} else {
length = 0;
outLength = 0;
}
prog_end_ptr = code_pos;
} catch (ScriptException& exc) {
exc;
length = 0;
outLength = 0;
prog_end_ptr = code_pos;
}
parsetree_freeall();
return length;
return success;
}
str ScriptCompiler::GetLine(str content, int line)

View file

@ -163,8 +163,8 @@ public:
char *Preprocess(char *sourceBuffer);
void Preclean(char *processedBuffer);
size_t Parse(GameScript *m_GameScript, char *sourceBuffer, const char *type);
size_t Compile(GameScript *m_GameScript, unsigned char *progBuffer);
bool Parse(GameScript *m_GameScript, char *sourceBuffer, const char *type, size_t& outLength);
bool Compile(GameScript *m_GameScript, unsigned char *progBuffer, size_t& outLength);
static str GetLine(str content, int line);