mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00

This fixes #311 where a memory corruption that occurred in ARM was caused because of insufficient ScriptVM stack size. The stack size was incorrectly calculated because the stack offset was using unsigned values instead of signed in ARM.
182 lines
6.6 KiB
C++
182 lines
6.6 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2008 the OpenMoHAA team
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
// compiler.h: Script Compiler
|
|
|
|
#pragma once
|
|
|
|
#include "../script/scriptopcodes.h"
|
|
#include "../fgame/gamescript.h"
|
|
#include "../parser/parsetree.h"
|
|
|
|
class ScriptVariable;
|
|
|
|
typedef void (*ScriptDisplayTokenFunc)(const char *type, const char *name);
|
|
|
|
typedef struct scriptmacro {
|
|
str name;
|
|
str parameters;
|
|
} scriptmacro_t;
|
|
|
|
#define BREAK_JUMP_LOCATION_COUNT 100
|
|
#define CONTINUE_JUMP_LOCATION_COUNT 100
|
|
|
|
class ScriptCompiler
|
|
{
|
|
public:
|
|
unsigned char *code_pos;
|
|
unsigned char *code_ptr;
|
|
unsigned char *prog_ptr;
|
|
unsigned char *prog_end_ptr;
|
|
|
|
GameScript *script;
|
|
StateScript *stateScript;
|
|
|
|
bool bCanBreak;
|
|
bool bCanContinue;
|
|
|
|
opcode_info_t prev_opcodes[100];
|
|
unsigned int prev_opcode_pos;
|
|
|
|
int m_iVarStackOffset;
|
|
int m_iInternalMaxVarStackOffset;
|
|
int m_iMaxExternalVarStackOffset;
|
|
int m_iMaxCallStackOffset;
|
|
int m_iHasExternal;
|
|
|
|
unsigned char *apucBreakJumpLocations[BREAK_JUMP_LOCATION_COUNT];
|
|
int iBreakJumpLocCount;
|
|
unsigned char *apucContinueJumpLocations[CONTINUE_JUMP_LOCATION_COUNT];
|
|
int iContinueJumpLocCount;
|
|
|
|
bool compileSuccess;
|
|
|
|
static int current_label;
|
|
|
|
public:
|
|
ScriptCompiler();
|
|
void Reset();
|
|
|
|
unsigned char PrevOpcode();
|
|
signed char PrevVarStackOffset();
|
|
void AbsorbPrevOpcode();
|
|
void ClearPrevOpcode();
|
|
void AccumulatePrevOpcode(int opcode, int iVarStackOffset);
|
|
|
|
void AddBreakJumpLocation(unsigned char *pos);
|
|
void AddContinueJumpLocation(unsigned char *pos);
|
|
void AddJumpLocation(unsigned char *pos);
|
|
void AddJumpBackLocation(unsigned char *pos);
|
|
void AddJumpToLocation(unsigned char *pos);
|
|
|
|
bool BuiltinReadVariable(unsigned int sourcePos, int type, int eventnum);
|
|
bool BuiltinWriteVariable(unsigned int sourcePos, int type, int eventnum);
|
|
|
|
void EmitAssignmentStatement(sval_t lhs, unsigned int sourcePos);
|
|
|
|
void EmitBoolJumpFalse(unsigned int sourcePos);
|
|
void EmitBoolJumpTrue(unsigned int sourcePos);
|
|
void EmitBoolNot(unsigned int sourcePos);
|
|
void EmitBoolToVar(unsigned int sourcePos);
|
|
|
|
void EmitBreak(unsigned int sourcePos);
|
|
void EmitCatch(sval_t val, unsigned char *try_begin_code_pos, unsigned int sourcePos);
|
|
void EmitConstArray(sval_t lhs, sval_t rhs, unsigned int sourcePos);
|
|
void EmitConstArrayOpcode(int iCount);
|
|
void EmitContinue(unsigned int sourcePos);
|
|
void EmitDoWhileJump(sval_t while_stmt, sval_t while_expr, unsigned int sourcePos);
|
|
void EmitEof(unsigned int sourcePos);
|
|
void EmitField(sval_t listener_val, sval_t field_val, unsigned int sourcePos);
|
|
void EmitFloat(float value, unsigned int sourcePos);
|
|
void EmitFunc1(int opcode, unsigned int sourcePos);
|
|
//void EmitFunction(int iParamCount, sval_t val, unsigned int sourcePos);
|
|
void EmitIfElseJump(sval_t if_stmt, sval_t else_stmt, unsigned int sourcePos);
|
|
void EmitIfJump(sval_t if_stmt, unsigned int sourcePos);
|
|
void EmitInteger(unsigned int value, unsigned int sourcePos);
|
|
void EmitJump(unsigned char *pos, unsigned int sourcePos);
|
|
void EmitJumpBack(unsigned char *pos, unsigned int sourcePos);
|
|
void EmitLabel(const char *name, unsigned int sourcePos);
|
|
void EmitLabel(int name, unsigned int sourcePos);
|
|
void EmitLabelParameterList(sval_t parameter_list, unsigned int sourcePos);
|
|
void EmitLabelPrivate(const char *name, unsigned int sourcePos);
|
|
void EmitAndJump(sval_t logic_stmt, unsigned int sourcePos);
|
|
void EmitOrJump(sval_t logic_stmt, unsigned int sourcePos);
|
|
void EmitMakeArray(sval_t val);
|
|
void EmitMethodExpression(int iParamCount, int eventnum, unsigned int sourcePos);
|
|
void EmitNil(unsigned int sourcePos);
|
|
void EmitNop();
|
|
int EmitNot(unsigned int sourcePos);
|
|
void EmitOpcode(int opcode, unsigned int sourcePos);
|
|
void EmitParameter(sval_u lhs, unsigned int sourcePos);
|
|
int EmitParameterList(sval_t event_parameter_list);
|
|
void EmitRef(sval_t val, unsigned int sourcePos);
|
|
void EmitStatementList(sval_t val);
|
|
void EmitString(str value, unsigned int sourcePos);
|
|
void EmitSwitch(sval_t val, unsigned int sourcePos);
|
|
void EmitValue(sval_t val);
|
|
void EmitValue(ScriptVariable& var, unsigned int sourcePos);
|
|
void EmitVarToBool(unsigned int sourcePos);
|
|
void EmitWhileJump(sval_t while_expr, sval_t while_stmt, sval_t inc_stmt, unsigned int sourcePos);
|
|
|
|
bool EvalPrevValue(ScriptVariable& var);
|
|
|
|
void ProcessBreakJumpLocations(int iStartBreakJumpLocCount);
|
|
void ProcessContinueJumpLocations(int iStartContinueJumpLocCount);
|
|
|
|
unsigned char *GetPosition();
|
|
|
|
// compile
|
|
void CompileError(unsigned int sourcePos, const char *format, ...);
|
|
|
|
scriptmacro_t *GetMacro(char *sourceLine);
|
|
|
|
char *Preprocess(char *sourceBuffer);
|
|
void Preclean(char *processedBuffer);
|
|
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);
|
|
|
|
private:
|
|
template<typename Value>
|
|
void EmitOpcodeValue(const Value& value, size_t size);
|
|
|
|
template<typename Value>
|
|
void EmitOpcodeValue(const Value& value);
|
|
|
|
template<typename Value>
|
|
void EmitAt(unsigned char *location, const Value& value, size_t size);
|
|
|
|
template<typename Value>
|
|
void SetOpcodeValue(const Value& value);
|
|
|
|
template<typename Value>
|
|
Value GetOpcodeValue(size_t size) const;
|
|
|
|
template<typename Value>
|
|
Value GetOpcodeValue(size_t offset, size_t size) const;
|
|
};
|
|
|
|
extern ScriptCompiler Compiler;
|
|
|
|
void CompileAssemble(const char *filename, const char *outputfile);
|
|
bool GetCompiledScript(GameScript *scr);
|