HyperDbg/hyperdbg/script-engine/code/script-engine.c

3094 lines
86 KiB
C
Raw Normal View History

/**
2021-06-10 17:33:05 +04:30
* @file script-engine.c
2022-01-18 22:38:56 +03:30
* @author M.H. Gholamrezaei (mh@hyperdbg.org)
* @author Sina Karvandi (sina@hyperdbg.org)
2020-10-22 18:56:58 +03:30
* @brief Script engine parser and codegen
* @details
* @version 0.1
* @date 2020-10-22
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
2021-03-03 16:53:19 +03:30
2023-01-18 20:23:40 +09:00
// #define _SCRIPT_ENGINE_LALR_DBG_EN
// #define _SCRIPT_ENGINE_LL1_DBG_EN
// #define _SCRIPT_ENGINE_CODEGEN_DBG_EN
/**
2022-05-18 16:00:16 +09:00
* @brief Converts name to address
2023-01-18 20:23:40 +09:00
*
* @param FunctionOrVariableName
* @param WasFound
* @return UINT64
2022-05-10 15:08:24 +04:30
*/
UINT64
ScriptEngineConvertNameToAddress(const char * FunctionOrVariableName, PBOOLEAN WasFound)
{
//
// A wrapper for pdb parser
//
return SymConvertNameToAddress(FunctionOrVariableName, WasFound);
2021-05-30 20:25:07 +04:30
}
/**
2023-01-18 20:23:40 +09:00
*
2022-05-18 16:00:16 +09:00
Load symbol files
2023-01-18 20:23:40 +09:00
*
* @param BaseAddress
* @param PdbFileName
* @param CustomModuleName
*
2023-01-18 20:23:40 +09:00
* @return UINT32
2022-05-10 15:08:24 +04:30
*/
2021-05-31 20:13:18 +04:30
UINT32
ScriptEngineLoadFileSymbol(UINT64 BaseAddress, const char * PdbFileName, const char * CustomModuleName)
2021-05-30 20:25:07 +04:30
{
//
// A wrapper for pdb parser
//
return SymLoadFileSymbol(BaseAddress, PdbFileName, CustomModuleName);
2021-05-31 20:13:18 +04:30
}
/**
2022-05-10 15:08:24 +04:30
* @brief Set the message handler as an alternative to printf
2023-01-18 20:23:40 +09:00
*
* @param Handler
* @return VOID
2022-05-10 15:08:24 +04:30
*/
VOID
ScriptEngineSetTextMessageCallback(PVOID Handler)
{
SymSetTextMessageCallback(Handler);
}
2022-05-10 15:08:24 +04:30
/**
* @brief Unload all the previously loaded symbols
2023-01-18 20:23:40 +09:00
*
* @return UINT32
2022-05-10 15:08:24 +04:30
*/
2021-05-31 20:13:18 +04:30
UINT32
ScriptEngineUnloadAllSymbols()
{
//
// A wrapper for pdb unloader
//
return SymUnloadAllSymbols();
}
2022-05-10 15:08:24 +04:30
/**
* @brief Unload a special pdb
2023-01-18 20:23:40 +09:00
*
* @param ModuleName
* @return UINT32
2022-05-10 15:08:24 +04:30
*/
UINT32
ScriptEngineUnloadModuleSymbol(char * ModuleName)
{
//
// A wrapper for pdb unloader
//
return SymUnloadModuleSymbol(ModuleName);
}
2022-05-10 15:08:24 +04:30
/**
* @brief Search for a special mask
2023-01-18 20:23:40 +09:00
*
* @param SearchMask
* @return UINT32
2022-05-10 15:08:24 +04:30
*/
2021-05-31 20:13:18 +04:30
UINT32
ScriptEngineSearchSymbolForMask(const char * SearchMask)
2021-05-31 20:13:18 +04:30
{
//
// A wrapper for pdb mask searcher
//
return SymSearchSymbolForMask(SearchMask);
}
2022-05-10 15:08:24 +04:30
/**
* @brief Get offset of a field from the structure
2023-01-18 20:23:40 +09:00
*
* @param TypeName
* @param FieldName
* @param FieldOffset
* @return BOOLEAN
2022-05-10 15:08:24 +04:30
*/
BOOLEAN
ScriptEngineGetFieldOffset(CHAR * TypeName, CHAR * FieldName, UINT32 * FieldOffset)
{
//
// A wrapper for search for fields in the structure
//
return SymGetFieldOffset(TypeName, FieldName, FieldOffset);
}
2022-05-10 15:08:24 +04:30
/**
* @brief Get size of a data type (structure)
2023-01-18 20:23:40 +09:00
*
* @param TypeName
* @param TypeSize
* @return BOOLEAN
2022-05-10 15:08:24 +04:30
*/
BOOLEAN
ScriptEngineGetDataTypeSize(CHAR * TypeName, UINT64 * TypeSize)
{
//
// A wrapper for getting size of the structure
//
return SymGetDataTypeSize(TypeName, TypeSize);
}
2022-05-10 15:08:24 +04:30
/**
* @brief Create symbol table for disassembler
2023-01-18 20:23:40 +09:00
*
* @param CallbackFunction
* @return BOOLEAN
2022-05-10 15:08:24 +04:30
*/
BOOLEAN
ScriptEngineCreateSymbolTableForDisassembler(void * CallbackFunction)
{
//
// A wrapper for pdb symbol table callback creator
//
return SymCreateSymbolTableForDisassembler(CallbackFunction);
}
2022-05-10 15:08:24 +04:30
/**
* @brief Convert local file to pdb path
2023-01-18 20:23:40 +09:00
*
* @param LocalFilePath
* @param ResultPath
* @return BOOLEAN
2022-05-10 15:08:24 +04:30
*/
BOOLEAN
ScriptEngineConvertFileToPdbPath(const char * LocalFilePath, char * ResultPath)
{
//
// A wrapper for pdb to path converter
//
return SymConvertFileToPdbPath(LocalFilePath, ResultPath);
}
2022-05-10 15:08:24 +04:30
/**
* @brief Initial load of the symbols
2023-01-18 20:23:40 +09:00
*
* @param BufferToStoreDetails
* @param StoredLength
* @param DownloadIfAvailable
* @param SymbolPath
* @param IsSilentLoad
* @return BOOLEAN
2022-05-10 15:08:24 +04:30
*/
2021-06-10 08:10:18 -07:00
BOOLEAN
2021-06-27 19:48:25 +04:30
ScriptEngineSymbolInitLoad(PVOID BufferToStoreDetails,
UINT32 StoredLength,
BOOLEAN DownloadIfAvailable,
const char * SymbolPath,
BOOLEAN IsSilentLoad)
2021-06-10 17:33:05 +04:30
{
//
// A wrapper for pdb and modules parser
//
return SymbolInitLoad(BufferToStoreDetails, StoredLength, DownloadIfAvailable, SymbolPath, IsSilentLoad);
2021-06-10 17:33:05 +04:30
}
2022-05-10 15:08:24 +04:30
/**
* @brief Show data based on symbol types
2023-01-18 20:23:40 +09:00
*
* @param TypeName
* @param Address
* @param IsStruct
* @param BufferAddress
* @param AdditionalParameters
* @return BOOLEAN
2022-05-10 15:08:24 +04:30
*/
2022-04-07 12:45:48 +04:30
BOOLEAN
ScriptEngineShowDataBasedOnSymbolTypes(const char * TypeName,
2022-04-07 23:07:05 +04:30
UINT64 Address,
BOOLEAN IsStruct,
2022-04-07 23:07:05 +04:30
PVOID BufferAddress,
const char * AdditionalParameters)
2022-04-07 12:45:48 +04:30
{
//
// A wrapper for showing types and data within structures
//
return SymShowDataBasedOnSymbolTypes(TypeName, Address, IsStruct, BufferAddress, AdditionalParameters);
2022-04-07 12:45:48 +04:30
}
2022-05-10 15:08:24 +04:30
/**
* @brief Cancel loading
2023-01-18 20:23:40 +09:00
*
* @return VOID
2022-05-10 15:08:24 +04:30
*/
VOID
ScriptEngineSymbolAbortLoading()
{
//
// A wrapper for aborting download and reload
//
SymbolAbortLoading();
}
2022-05-10 15:08:24 +04:30
/**
* @brief Convert file to pdb attributes for symbols
2023-01-18 20:23:40 +09:00
*
* @param LocalFilePath
* @param PdbFilePath
* @param GuidAndAgeDetails
* @param Is32BitModule
*
2023-01-18 20:23:40 +09:00
* @return BOOLEAN
2022-05-10 15:08:24 +04:30
*/
2021-06-10 02:54:32 +04:30
BOOLEAN
ScriptEngineConvertFileToPdbFileAndGuidAndAgeDetails(const char * LocalFilePath, char * PdbFilePath, char * GuidAndAgeDetails, BOOLEAN Is32BitModule)
2021-06-10 02:54:32 +04:30
{
//
// A wrapper for pdb to path file and guid and age detail converter
//
return SymConvertFileToPdbFileAndGuidAndAgeDetails(LocalFilePath, PdbFilePath, GuidAndAgeDetails, Is32BitModule);
2021-06-10 02:54:32 +04:30
}
2020-10-20 19:35:15 +03:30
/**
2022-05-18 16:00:16 +09:00
* @brief The entry point of script engine
2023-01-18 20:23:40 +09:00
*
* @param str
* @return PSYMBOL_BUFFER
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
PSYMBOL_BUFFER
ScriptEngineParse(char * str)
2020-10-20 19:35:15 +03:30
{
2022-05-08 01:00:24 +09:00
PTOKEN_LIST Stack = NewTokenList();
2022-05-18 23:44:03 +04:30
PTOKEN_LIST MatchedStack = NewTokenList();
2021-04-11 18:27:23 +04:30
PSYMBOL_BUFFER CodeBuffer = NewSymbolBuffer();
2020-10-20 19:35:15 +03:30
// will modify here later
PSYMBOL_BUFFER UserDefinedFunctions = NewSymbolBuffer();
2021-06-27 19:48:25 +04:30
SCRIPT_ENGINE_ERROR_TYPE Error = SCRIPT_ENGINE_ERROR_FREE;
char * ErrorMessage = NULL;
2021-03-22 18:19:39 +04:30
static FirstCall = 1;
2021-03-03 16:53:19 +03:30
if (FirstCall)
{
IdTable = NewTokenList();
FunctionParameterIdTable = NewTokenList();
FirstCall = 0;
2021-03-03 16:53:19 +03:30
}
2022-05-18 23:44:03 +04:30
PTOKEN TopToken = NewUnknownToken();
2020-12-02 02:32:49 +03:30
2021-03-22 18:19:39 +04:30
int NonTerminalId;
int TerminalId;
int RuleId;
2020-10-20 19:35:15 +03:30
char c;
2021-04-13 22:53:02 +04:30
BOOL WaitForWaitStatementBooleanExpression = FALSE;
2020-10-24 14:36:07 +03:30
2020-12-03 18:02:49 +03:30
//
2021-03-22 18:19:39 +04:30
// Initialize Scanner
//
InputIdx = 0;
CurrentLine = 0;
2020-12-03 18:02:49 +03:30
CurrentLineIdx = 0;
2021-03-22 18:19:39 +04:30
2020-10-20 19:35:15 +03:30
//
// End of File Token
//
2022-05-07 22:51:55 +09:00
PTOKEN EndToken = NewToken(END_OF_STACK, "$");
2022-05-18 23:44:03 +04:30
2020-10-20 19:35:15 +03:30
//
// Start Token
//
2022-05-07 22:51:55 +09:00
PTOKEN StartToken = NewToken(NON_TERMINAL, START_VARIABLE);
2020-10-20 19:35:15 +03:30
Push(Stack, EndToken);
Push(Stack, StartToken);
c = sgetc(str);
2020-10-22 18:08:20 +03:30
2022-05-07 22:51:55 +09:00
PTOKEN CurrentIn = Scan(str, &c);
2020-10-24 14:36:07 +03:30
if (CurrentIn->Type == UNKNOWN)
{
2021-06-27 19:48:25 +04:30
Error = SCRIPT_ENGINE_ERROR_SYNTAX;
ErrorMessage = HandleError(&Error, str);
CodeBuffer->Message = ErrorMessage;
2020-12-02 02:32:49 +03:30
2020-10-24 14:36:07 +03:30
RemoveTokenList(Stack);
RemoveTokenList(MatchedStack);
2022-05-19 20:16:57 +09:00
RemoveToken(&CurrentIn);
2020-10-24 14:36:07 +03:30
return CodeBuffer;
}
2020-10-20 19:35:15 +03:30
do
{
2022-05-19 20:16:57 +09:00
RemoveToken(&TopToken);
2020-10-20 19:35:15 +03:30
TopToken = Pop(Stack);
2021-06-27 19:48:25 +04:30
#ifdef _SCRIPT_ENGINE_LL1_DBG_EN
2020-10-20 19:35:15 +03:30
printf("\nTop Token :\n");
PrintToken(TopToken);
printf("\nCurrent Input :\n");
PrintToken(CurrentIn);
printf("\n");
#endif
2020-12-02 02:32:49 +03:30
2020-10-20 19:35:15 +03:30
if (TopToken->Type == NON_TERMINAL)
{
2021-06-27 19:48:25 +04:30
if (!strcmp(TopToken->Value, "BOOLEAN_EXPRESSION"))
2020-10-20 19:35:15 +03:30
{
UINT64 BooleanExpressionSize = BooleanExpressionExtractEnd(str, &WaitForWaitStatementBooleanExpression, CurrentIn);
ScriptEngineBooleanExpresssionParse(BooleanExpressionSize, CurrentIn, MatchedStack, UserDefinedFunctions, CodeBuffer, str, &c, &Error);
2021-06-27 19:48:25 +04:30
if (Error != SCRIPT_ENGINE_ERROR_FREE)
2021-04-11 18:27:23 +04:30
{
2021-06-27 19:48:25 +04:30
break;
2021-04-11 18:27:23 +04:30
}
2022-05-19 20:16:57 +09:00
RemoveToken(&CurrentIn);
CurrentIn = Scan(str, &c);
2021-06-27 19:48:25 +04:30
if (CurrentIn->Type == UNKNOWN)
{
Error = SCRIPT_ENGINE_ERROR_UNKNOWN_TOKEN;
2021-06-27 19:48:25 +04:30
break;
}
2022-05-19 20:16:57 +09:00
RemoveToken(&CurrentIn);
2021-04-11 18:27:23 +04:30
CurrentIn = Scan(str, &c);
2021-04-12 18:19:14 +04:30
if (CurrentIn->Type == UNKNOWN)
{
Error = SCRIPT_ENGINE_ERROR_UNKNOWN_TOKEN;
2021-06-27 19:48:25 +04:30
break;
2021-04-12 18:19:14 +04:30
}
2022-05-19 20:16:57 +09:00
RemoveToken(&TopToken);
2021-04-12 18:19:14 +04:30
TopToken = Pop(Stack);
2020-10-20 19:35:15 +03:30
}
else
2020-10-20 19:35:15 +03:30
{
NonTerminalId = GetNonTerminalId(TopToken);
if (NonTerminalId == INVALID)
{
2021-06-27 19:48:25 +04:30
Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
2024-03-17 20:33:02 +09:00
TerminalId = GetTerminalId(CurrentIn);
if (TerminalId == INVALID)
{
2021-06-27 19:48:25 +04:30
Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
2024-03-17 20:33:02 +09:00
2021-02-25 23:36:27 +03:30
RuleId = ParseTable[NonTerminalId][TerminalId];
if (RuleId == INVALID)
{
2021-06-27 19:48:25 +04:30
Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
2020-10-20 19:35:15 +03:30
//
// Push RHS Reversely into stack
//
for (int i = RhsSize[RuleId] - 1; i >= 0; i--)
{
PTOKEN Token = (PTOKEN)&Rhs[RuleId][i];
2020-10-20 19:35:15 +03:30
if (Token->Type == EPSILON)
break;
2021-06-27 19:48:25 +04:30
2022-05-07 22:51:55 +09:00
PTOKEN DuplicatedToken = CopyToken(Token);
2021-06-27 19:48:25 +04:30
Push(Stack, DuplicatedToken);
}
2020-10-20 19:35:15 +03:30
}
}
else if (TopToken->Type == SEMANTIC_RULE)
{
if (!strcmp(TopToken->Value, "@PUSH"))
{
2022-05-19 20:16:57 +09:00
RemoveToken(&TopToken);
2020-10-20 19:35:15 +03:30
TopToken = Pop(Stack);
2021-06-27 19:48:25 +04:30
2020-10-20 19:35:15 +03:30
Push(MatchedStack, CurrentIn);
2020-11-29 23:09:39 +03:30
2020-10-20 19:35:15 +03:30
CurrentIn = Scan(str, &c);
2020-10-24 14:36:07 +03:30
if (CurrentIn->Type == UNKNOWN)
{
2021-06-27 19:48:25 +04:30
Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
2020-10-24 14:36:07 +03:30
}
2020-10-20 19:35:15 +03:30
}
2021-04-13 22:53:02 +04:30
2020-10-20 19:35:15 +03:30
else
{
2021-04-13 22:53:02 +04:30
if (!strcmp(TopToken->Value, "@START_OF_FOR"))
{
WaitForWaitStatementBooleanExpression = TRUE;
}
CodeGen(MatchedStack, UserDefinedFunctions, CodeBuffer, TopToken, &Error);
2021-06-27 19:48:25 +04:30
if (Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2020-10-20 19:35:15 +03:30
}
}
else
{
if (!IsEqual(TopToken, CurrentIn))
{
2021-06-27 19:48:25 +04:30
Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
2020-10-20 19:35:15 +03:30
}
else
{
2022-05-19 20:16:57 +09:00
RemoveToken(&CurrentIn);
2020-10-20 19:35:15 +03:30
CurrentIn = Scan(str, &c);
2020-11-29 23:09:39 +03:30
2020-12-03 18:02:49 +03:30
if (CurrentIn->Type == UNKNOWN)
{
2021-06-27 19:48:25 +04:30
Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
2020-12-03 18:02:49 +03:30
}
2020-10-20 19:35:15 +03:30
}
}
2021-06-27 19:48:25 +04:30
#ifdef _SCRIPT_ENGINE_LL1_DBG_EN
2021-04-10 19:29:21 +04:30
printf("Stack: \n");
2021-03-22 18:19:39 +04:30
PrintTokenList(Stack);
printf("\n");
2020-10-20 19:35:15 +03:30
#endif
2021-03-22 18:19:39 +04:30
} while (TopToken->Type != END_OF_STACK);
2020-10-20 19:35:15 +03:30
if (Error != SCRIPT_ENGINE_ERROR_FREE)
2021-06-27 19:48:25 +04:30
{
ErrorMessage = HandleError(&Error, str);
CleanTempList();
}
2022-03-19 03:05:07 +03:30
else
{
ErrorMessage = NULL;
2021-06-27 19:48:25 +04:30
}
CodeBuffer->Message = ErrorMessage;
2021-09-05 21:55:42 +09:00
if (Stack)
2021-06-27 19:48:25 +04:30
RemoveTokenList(Stack);
if (MatchedStack)
RemoveTokenList(MatchedStack);
if (UserDefinedFunctions)
RemoveSymbolBuffer(UserDefinedFunctions);
2021-06-27 19:48:25 +04:30
if (CurrentIn)
2022-05-19 20:16:57 +09:00
RemoveToken(&CurrentIn);
2021-06-27 19:48:25 +04:30
if (TopToken)
2022-05-19 20:16:57 +09:00
RemoveToken(&TopToken);
2021-04-10 19:29:21 +04:30
if (FunctionParameterIdTable)
{
RemoveTokenList(FunctionParameterIdTable);
FunctionParameterIdTable = NewTokenList();
}
2021-03-22 18:19:39 +04:30
return CodeBuffer;
}
2020-10-20 19:35:15 +03:30
2022-05-10 15:08:24 +04:30
/**
2023-01-18 20:23:40 +09:00
* @brief Script Engine code generator
*
* @param MatchedStack
* @param CodeBuffer
* @param Operator
* @param Error
2022-05-10 15:08:24 +04:30
*/
2021-04-11 18:27:23 +04:30
void
CodeGen(PTOKEN_LIST MatchedStack, PSYMBOL_BUFFER UserDefinedFunctions, PSYMBOL_BUFFER CodeBuffer, PTOKEN Operator, PSCRIPT_ENGINE_ERROR_TYPE Error)
2020-10-20 19:35:15 +03:30
{
2022-05-18 23:44:03 +04:30
PTOKEN Op0 = NULL;
PTOKEN Op1 = NULL;
PTOKEN Op2 = NULL;
PTOKEN Temp = NULL;
PSYMBOL OperatorSymbol = NULL;
PSYMBOL Op0Symbol = NULL;
PSYMBOL Op1Symbol = NULL;
PSYMBOL Op2Symbol = NULL;
PSYMBOL TempSymbol = NULL;
VARIABLE_TYPE * VariableType = NULL;
2020-10-20 19:35:15 +03:30
//
// It is in user-defined function if CurrentFunctionSymbol is not null
//
static PSYMBOL CurrentFunctionSymbol = NULL;
OperatorSymbol = ToSymbol(Operator, Error);
2020-10-20 19:35:15 +03:30
2021-06-27 19:48:25 +04:30
#ifdef _SCRIPT_ENGINE_CODEGEN_DBG_EN
//
// Print Debug Info
//
printf("Operator :\n");
PrintToken(Operator);
printf("\n");
2020-10-20 19:35:15 +03:30
2021-06-27 19:48:25 +04:30
printf("Semantic Stack:\n");
PrintTokenList(MatchedStack);
printf("\n");
2020-10-20 19:35:15 +03:30
2021-06-27 19:48:25 +04:30
printf("Code Buffer:\n");
PrintSymbolBuffer(CodeBuffer);
printf(".\n.\n.\n\n");
#endif
2020-12-03 20:54:33 +03:30
2021-06-27 19:48:25 +04:30
while (TRUE)
2021-02-12 03:12:01 +03:30
{
if (IsVariableType(Operator))
{
PTOKEN PToken = CopyToken(Operator);
PToken->Type = INPUT_VARIABLE_TYPE;
Push(MatchedStack, PToken);
}
else if (!strcmp(Operator->Value, "@START_OF_USER_DEFINED_FUNCTION"))
{
Op0 = Pop(MatchedStack);
VariableType = HandleType(MatchedStack);
if (VariableType == VARIABLE_TYPE_UNKNOWN)
{
*Error = SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE;
break;
}
UINT64 CurrentPointer = CodeBuffer->Pointer;
//
// Add jmp instruction to Code Buffer
//
PSYMBOL JumpInstruction = NewSymbol();
JumpInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JumpInstruction->Value = FUNC_JMP;
PushSymbol(CodeBuffer, JumpInstruction);
RemoveSymbol(&JumpInstruction);
//
// Push jump address
//
PSYMBOL JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_NUM_TYPE;
JumpAddressSymbol->Value = 0xffffffffffffffff;
PushSymbol(CodeBuffer, JumpAddressSymbol);
RemoveSymbol(&JumpAddressSymbol);
PushSymbol(UserDefinedFunctions, NewFunctionSymbol(Op0->Value, VariableType));
CurrentFunctionSymbol = NewFunctionSymbol(Op0->Value, VariableType);
PushSymbol(CodeBuffer, CurrentFunctionSymbol);
PushSymbol(CodeBuffer, OperatorSymbol);
PSYMBOL StackTempNumberSymbol = NewSymbol();
StackTempNumberSymbol->Type = SYMBOL_NUM_TYPE;
StackTempNumberSymbol->Value = 0xffffffffffffffff;
PushSymbol(CodeBuffer, StackTempNumberSymbol);
RemoveSymbol(&StackTempNumberSymbol);
}
else if (!strcmp(Operator->Value, "@FUNCTION_PARAMETER"))
{
Op0 = Pop(MatchedStack);
VariableType = HandleType(MatchedStack);
if (VariableType == VARIABLE_TYPE_UNKNOWN)
{
*Error = SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE;
break;
}
Op0Symbol = NewSymbol();
2024-03-17 20:33:02 +09:00
free((void *)Op0Symbol->Value);
Op0Symbol->Value = NewFunctionParameterIdentifier(Op0);
SetType(&Op0Symbol->Type, SYMBOL_FUNCTION_PARAMETER_ID_TYPE);
PushSymbol(UserDefinedFunctions, Op0Symbol);
}
else if (!strcmp(Operator->Value, "@END_OF_USER_DEFINED_FUNCTION"))
{
PushSymbol(CodeBuffer, OperatorSymbol);
UINT64 CurrentPointer = CodeBuffer->Pointer;
PSYMBOL Symbol = NULL;
2024-03-17 20:33:02 +09:00
BOOL Found = FALSE;
unsigned int i = 0;
// for loop not able to begin from CodeBuffer->Pointer to 0 because of string and wstring's size
for (; i < CodeBuffer->Pointer;)
{
Symbol = CodeBuffer->Head + i;
2024-03-17 20:33:02 +09:00
if (Symbol->Type == SYMBOL_USER_DEFINED_FUNCTION_TYPE && !strcmp((const char *)CurrentFunctionSymbol->Value, (const char *)Symbol->Value))
{
Found = TRUE;
break;
}
else if (Symbol->Type == SYMBOL_STRING_TYPE || Symbol->Type == SYMBOL_WSTRING_TYPE)
{
int temp = GetSymbolHeapSize(Symbol);
i += temp;
}
else
{
i++;
}
}
if (!Found)
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
//
2024-03-17 18:49:51 +09:00
// skip executing user-defined function first time
//
Symbol = CodeBuffer->Head + i - 1;
Symbol->Value = CurrentPointer;
2024-03-17 20:48:07 +09:00
long long unsigned StackTempNumber = 0;
for (int j = i; j < CurrentPointer; j++)
{
Symbol = CodeBuffer->Head + j;
if (Symbol->Type == SYMBOL_STACK_TEMP_TYPE && (Symbol->Value + 1) > StackTempNumber)
{
StackTempNumber = Symbol->Value + 1;
}
}
Symbol = CodeBuffer->Head + i + 2;
Symbol->Value = StackTempNumber;
CurrentFunctionSymbol = NULL;
}
else if (!strcmp(Operator->Value, "@RETURN_OF_USER_DEFINED_FUNCTION_WITHOUT_VALUE"))
{
if (!CurrentFunctionSymbol)
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
2024-03-17 20:33:02 +09:00
if (CurrentFunctionSymbol->VariableType != (unsigned long long)VARIABLE_TYPE_VOID)
{
*Error = SCRIPT_ENGINE_ERROR_NON_VOID_FUNCTION_NOT_RETURNING_VALUE;
break;
}
PushSymbol(CodeBuffer, OperatorSymbol);
}
else if (!strcmp(Operator->Value, "@RETURN_OF_USER_DEFINED_FUNCTION_WITH_VALUE"))
{
if (!CurrentFunctionSymbol)
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
2024-03-17 20:33:02 +09:00
if (CurrentFunctionSymbol->VariableType == (unsigned long long)VARIABLE_TYPE_VOID)
{
*Error = SCRIPT_ENGINE_ERROR_VOID_FUNCTION_RETURNING_VALUE;
break;
}
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
PushSymbol(CodeBuffer, Op0Symbol);
FreeTemp(Op0);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
}
else if (!strcmp(Operator->Value, "@CALL_USER_DEFINED_FUNCTION"))
{
2024-03-17 20:33:02 +09:00
PSYMBOL Symbol = NULL;
unsigned int i = 0;
PTOKEN FunctionToken = Top(MatchedStack);
BOOL Found = FALSE;
//
// find function's address
//
for (; i < CodeBuffer->Pointer;)
{
Symbol = CodeBuffer->Head + i;
2024-03-17 20:33:02 +09:00
if (Symbol->Type == SYMBOL_USER_DEFINED_FUNCTION_TYPE && !strcmp((const char *)FunctionToken->Value, (const char *)Symbol->Value))
{
Found = TRUE;
break;
}
else if (Symbol->Type == SYMBOL_STRING_TYPE || Symbol->Type == SYMBOL_WSTRING_TYPE)
{
int temp = GetSymbolHeapSize(Symbol);
i += temp;
}
else
{
i++;
}
}
if (!Found)
{
*Error = SCRIPT_ENGINE_ERROR_UNDEFINED_FUNCTION;
break;
}
FunctionToken->Type = FUNCTION_TYPE;
PushSymbol(CodeBuffer, OperatorSymbol);
}
else if (!strcmp(Operator->Value, "@CALL_USER_DEFINED_FUNCTION_PARAMETER"))
{
// will rewrite here to input variable's type
PushSymbol(CodeBuffer, OperatorSymbol);
Op0Symbol = ToSymbol(Top(MatchedStack), Error);
PushSymbol(CodeBuffer, Op0Symbol);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
}
else if (!strcmp(Operator->Value, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITHOUT_RETURNING_VALUE") || !strcmp(Operator->Value, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE"))
{
2024-03-17 20:33:02 +09:00
PSYMBOL Symbol = NULL;
unsigned int i = 0;
int TargetFunctionVariableNum = 0;
int VariableNum = 0;
PTOKEN FunctionToken = NULL;
BOOL Found = FALSE;
PTOKEN ReturnValueToken = NULL;
while (MatchedStack->Pointer > 0)
{
FunctionToken = Pop(MatchedStack);
if (FunctionToken->Type == FUNCTION_TYPE)
{
break;
}
else
{
VariableNum++;
// RemoveToken(&FunctionToken);
}
}
//
// find function's address
//
for (; i < CodeBuffer->Pointer;)
{
Symbol = CodeBuffer->Head + i;
2024-03-17 20:33:02 +09:00
if (Symbol->Type == SYMBOL_USER_DEFINED_FUNCTION_TYPE && !strcmp((const char *)FunctionToken->Value, (const char *)Symbol->Value))
{
Found = TRUE;
break;
}
else if (Symbol->Type == SYMBOL_STRING_TYPE || Symbol->Type == SYMBOL_WSTRING_TYPE)
{
int temp = GetSymbolHeapSize(Symbol);
i += temp;
}
else
{
i++;
}
}
if (!Found)
{
*Error = SCRIPT_ENGINE_ERROR_UNDEFINED_FUNCTION;
break;
}
// will rewrite here
2024-03-17 20:33:02 +09:00
for (unsigned int j = 0; j < UserDefinedFunctions->Pointer; j++)
{
Symbol = UserDefinedFunctions->Head + j;
2024-03-17 20:33:02 +09:00
if (Symbol->Type == SYMBOL_USER_DEFINED_FUNCTION_TYPE && !strcmp((const char *)FunctionToken->Value, (const char *)Symbol->Value))
{
j++;
Symbol = UserDefinedFunctions->Head + j;
while (Symbol->Type != SYMBOL_USER_DEFINED_FUNCTION_TYPE && j < UserDefinedFunctions->Pointer)
{
TargetFunctionVariableNum++;
j++;
Symbol = UserDefinedFunctions->Head + j;
}
goto ExitLoop;
}
}
ExitLoop:
if (VariableNum != TargetFunctionVariableNum)
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
//
// Add call user-defined function instruction
//
PushSymbol(CodeBuffer, OperatorSymbol);
//
// Add function's address
//
PSYMBOL JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_NUM_TYPE;
JumpAddressSymbol->Value = i;
PushSymbol(CodeBuffer, JumpAddressSymbol);
RemoveSymbol(&JumpAddressSymbol);
//
// Add return address
//
JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_RETURN_ADDRESS_TYPE;
JumpAddressSymbol->Value = CodeBuffer->Pointer + 1;
PushSymbol(CodeBuffer, JumpAddressSymbol);
RemoveSymbol(&JumpAddressSymbol);
if (!strcmp(Operator->Value, "@END_OF_CALLING_USER_DEFINED_FUNCTION_WITH_RETURNING_VALUE"))
{
2024-03-17 20:33:02 +09:00
if (FunctionToken->Type == (TOKEN_TYPE)VARIABLE_TYPE_VOID)
{
*Error = SCRIPT_ENGINE_ERROR_VOID_FUNCTION_RETURNING_VALUE;
break;
}
//
// Add return variable symbol
//
2024-03-17 18:49:51 +09:00
Temp = NewTemp(Error, CurrentFunctionSymbol);
Push(MatchedStack, Temp);
PSYMBOL Symbol = NewSymbol();
Symbol->Type = SYMBOL_SEMANTIC_RULE_TYPE;
Symbol->Value = FUNC_MOV_RETURN_VALUE;
PushSymbol(CodeBuffer, Symbol);
RemoveSymbol(&Symbol);
TempSymbol = ToSymbol(Temp, Error);
PushSymbol(CodeBuffer, TempSymbol);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
}
RemoveToken(&FunctionToken);
}
else if (!strcmp(Operator->Value, "@MOV"))
2021-02-12 03:12:01 +03:30
{
2021-06-27 19:48:25 +04:30
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2021-02-12 03:12:01 +03:30
Op1 = Pop(MatchedStack);
if (Op1->Type == GLOBAL_UNRESOLVED_ID)
2021-02-12 03:12:01 +03:30
{
2021-09-05 21:55:42 +09:00
Op1Symbol = NewSymbol();
2024-03-17 20:33:02 +09:00
free((void *)Op1Symbol->Value);
Op1Symbol->Value = NewGlobalIdentifier(Op1);
SetType(&Op1Symbol->Type, SYMBOL_GLOBAL_ID_TYPE);
}
else if (Op1->Type == LOCAL_UNRESOLVED_ID)
{
Op1Symbol = NewSymbol();
2024-03-17 20:33:02 +09:00
free((void *)Op1Symbol->Value);
Op1Symbol->Value = NewLocalIdentifier(Op1);
SetType(&Op1Symbol->Type, SYMBOL_LOCAL_ID_TYPE);
2021-06-27 19:48:25 +04:30
}
else
{
Op1Symbol = ToSymbol(Op1, Error);
2021-02-12 03:12:01 +03:30
}
if (MatchedStack->Pointer > 0)
{
if (Top(MatchedStack)->Type == INPUT_VARIABLE_TYPE)
{
VariableType = HandleType(MatchedStack);
if (VariableType == VARIABLE_TYPE_UNKNOWN)
{
*Error = SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE;
break;
}
2024-03-17 20:48:07 +09:00
Op1Symbol->VariableType = (unsigned long long)VariableType;
}
}
2021-06-27 19:48:25 +04:30
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, Op1Symbol);
2021-02-12 03:12:01 +03:30
2021-06-27 19:48:25 +04:30
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
FreeTemp(Op1);
2022-05-18 13:26:57 +09:00
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-06-27 19:48:25 +04:30
}
else if (IsType2Func(Operator))
2021-02-12 03:12:01 +03:30
{
2021-06-27 19:48:25 +04:30
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2022-05-18 13:26:57 +09:00
PushSymbol(CodeBuffer, Op0Symbol);
2021-06-27 19:48:25 +04:30
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-02-12 03:12:01 +03:30
}
2021-06-27 19:48:25 +04:30
else if (IsType1Func(Operator))
{
2022-05-18 20:43:06 +09:00
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2021-02-12 03:12:01 +03:30
Temp = NewTemp(Error, CurrentFunctionSymbol);
2022-05-18 20:43:06 +09:00
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp, Error);
2021-05-19 15:17:14 +04:30
2022-05-18 20:43:06 +09:00
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, TempSymbol);
2022-05-18 12:54:31 +09:00
2022-05-18 20:43:06 +09:00
FreeTemp(Op0);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
2021-06-27 19:48:25 +04:30
{
2022-05-18 20:43:06 +09:00
break;
2021-06-27 19:48:25 +04:30
}
}
else if (IsType4Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
PSYMBOL_BUFFER TempStack = NewSymbolBuffer();
UINT32 OperandCount = 0;
do
{
if (Op1)
{
2022-05-19 20:16:57 +09:00
RemoveToken(&Op1);
2021-06-27 19:48:25 +04:30
}
Op1 = Pop(MatchedStack);
if (Op1->Type != SEMANTIC_RULE)
{
Op1Symbol = ToSymbol(Op1, Error);
2022-05-18 23:44:03 +04:30
2021-06-27 19:48:25 +04:30
FreeTemp(Op1);
2022-05-19 20:16:57 +09:00
PushSymbol(TempStack, Op1Symbol);
RemoveSymbol(&Op1Symbol);
2021-06-27 19:48:25 +04:30
OperandCount++;
2022-05-18 13:26:57 +09:00
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
2022-05-19 20:16:57 +09:00
RemoveSymbolBuffer(TempStack);
2022-05-18 13:26:57 +09:00
break;
}
2021-06-27 19:48:25 +04:30
}
2021-05-19 15:17:14 +04:30
2021-06-27 19:48:25 +04:30
} while (!(Op1->Type == SEMANTIC_RULE && !strcmp(Op1->Value, "@VARGSTART")));
2021-02-12 03:12:01 +03:30
2022-05-19 22:02:19 +09:00
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-06-27 19:48:25 +04:30
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2022-05-19 22:02:19 +09:00
FreeTemp(Op0);
2020-10-20 19:35:15 +03:30
2021-09-05 21:55:42 +09:00
char * Format = Op0->Value;
2021-06-27 19:48:25 +04:30
PSYMBOL OperandCountSymbol = NewSymbol();
OperandCountSymbol->Type = SYMBOL_VARIABLE_COUNT_TYPE;
OperandCountSymbol->Value = OperandCount;
2021-02-12 03:12:01 +03:30
2022-05-18 13:26:57 +09:00
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, OperandCountSymbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&OperandCountSymbol);
2021-06-27 19:48:25 +04:30
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
2022-05-19 20:16:57 +09:00
RemoveSymbolBuffer(TempStack);
2021-06-27 19:48:25 +04:30
break;
}
2021-04-13 22:53:02 +04:30
2023-11-21 06:34:20 +08:00
unsigned int FirstArgPointer = CodeBuffer->Pointer;
2021-09-05 21:55:42 +09:00
2024-03-17 20:33:02 +09:00
PSYMBOL Symbol;
unsigned int ArgCount = TempStack->Pointer;
2021-06-27 19:48:25 +04:30
for (int i = TempStack->Pointer - 1; i >= 0; i--)
{
Symbol = TempStack->Head + i;
PushSymbol(CodeBuffer, Symbol);
}
2023-11-21 06:34:20 +08:00
PSYMBOL FirstArg = (PSYMBOL)((unsigned long long)CodeBuffer->Head +
(unsigned long long)(FirstArgPointer * sizeof(SYMBOL)));
2022-05-19 20:16:57 +09:00
RemoveSymbolBuffer(TempStack);
2021-09-05 21:55:42 +09:00
UINT32 i = 0;
2021-09-05 21:55:42 +09:00
char * Str = Format;
do
{
//
// Not the best way but some how for optimization
//
if (*Str == '%')
{
CHAR Temp = *(Str + 1);
if (Temp == 'd' || Temp == 'i' || Temp == 'u' || Temp == 'o' ||
Temp == 'x' || Temp == 'c' || Temp == 'p' || Temp == 's' ||
!strncmp(Str, "%ws", 3) || !strncmp(Str, "%ls", 3) ||
!strncmp(Str, "%ld", 3) || !strncmp(Str, "%li", 3) ||
!strncmp(Str, "%lu", 3) || !strncmp(Str, "%lo", 3) ||
!strncmp(Str, "%lx", 3) ||
!strncmp(Str, "%hd", 3) || !strncmp(Str, "%hi", 3) ||
!strncmp(Str, "%hu", 3) || !strncmp(Str, "%ho", 3) ||
!strncmp(Str, "%hx", 3) ||
!strncmp(Str, "%lld", 4) || !strncmp(Str, "%lli", 4) ||
!strncmp(Str, "%llu", 4) || !strncmp(Str, "%llo", 4) ||
!strncmp(Str, "%llx", 4)
)
{
if (i < ArgCount)
{
Symbol = FirstArg + i;
}
else
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
Symbol->Type &= 0xffffffff;
Symbol->Type |= (UINT64)(Str - Format - 1) << 32;
i++;
}
}
Str++;
} while (*Str);
if (i != ArgCount)
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
}
2022-05-31 17:09:25 +04:30
2022-05-18 13:26:57 +09:00
if (*Error == SCRIPT_ENGINE_ERROR_SYNTAX)
{
break;
}
2021-06-27 19:48:25 +04:30
}
else if (IsType5Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
}
2021-08-20 20:25:48 +04:30
else if (!strcmp(Operator->Value, "@IGNORE_LVALUE"))
{
2022-05-18 23:44:03 +04:30
Op0 = Pop(MatchedStack);
2021-08-20 20:25:48 +04:30
}
2021-06-27 19:48:25 +04:30
else if (IsType6Func(Operator))
{
2022-05-18 20:43:06 +09:00
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2022-05-18 12:54:31 +09:00
2022-05-18 20:43:06 +09:00
Op1 = Pop(MatchedStack);
Op1Symbol = ToSymbol(Op1, Error);
2021-08-20 20:25:48 +04:30
2022-05-18 20:43:06 +09:00
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, Op1Symbol);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
2021-08-20 20:25:48 +04:30
{
2022-05-18 20:43:06 +09:00
break;
2021-08-20 20:25:48 +04:30
}
Temp = NewTemp(Error, CurrentFunctionSymbol);
2022-05-18 20:43:06 +09:00
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp, Error);
PushSymbol(CodeBuffer, TempSymbol);
2021-06-27 19:48:25 +04:30
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
FreeTemp(Op1);
}
2021-09-08 18:28:58 +09:00
else if (IsType7Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
Op1 = Pop(MatchedStack);
Op1Symbol = ToSymbol(Op1, Error);
2022-05-18 13:26:57 +09:00
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, Op1Symbol);
2021-09-08 18:28:58 +09:00
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
FreeTemp(Op1);
}
else if (IsType8Func(Operator))
{
2022-05-18 20:43:06 +09:00
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2021-09-08 18:28:58 +09:00
2022-05-18 20:43:06 +09:00
Op1 = Pop(MatchedStack);
Op1Symbol = ToSymbol(Op1, Error);
2021-09-08 18:28:58 +09:00
Op2 = Pop(MatchedStack);
Op2Symbol = ToSymbol(Op2, Error);
2021-09-08 18:28:58 +09:00
2022-05-18 20:43:06 +09:00
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, Op1Symbol);
PushSymbol(CodeBuffer, Op2Symbol);
2021-09-08 18:28:58 +09:00
Temp = NewTemp(Error, CurrentFunctionSymbol);
2022-05-18 20:43:06 +09:00
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp, Error);
PushSymbol(CodeBuffer, TempSymbol);
2021-09-08 18:28:58 +09:00
2022-05-18 20:43:06 +09:00
FreeTemp(Op2);
2022-05-18 23:44:03 +04:30
2021-09-08 18:28:58 +09:00
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
FreeTemp(Op1);
2022-05-18 20:43:06 +09:00
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-09-08 18:28:58 +09:00
}
else if (IsType14Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
Op1 = Pop(MatchedStack);
Op1Symbol = ToSymbol(Op1, Error);
Op2 = Pop(MatchedStack);
Op2Symbol = ToSymbol(Op2, Error);
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, Op1Symbol);
PushSymbol(CodeBuffer, Op2Symbol);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
FreeTemp(Op1);
FreeTemp(Op2);
}
2021-06-27 19:48:25 +04:30
else if (IsTwoOperandOperator(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2021-04-11 18:27:23 +04:30
2021-06-27 19:48:25 +04:30
Op1 = Pop(MatchedStack);
Op1Symbol = ToSymbol(Op1, Error);
2021-04-12 18:19:14 +04:30
Temp = NewTemp(Error, CurrentFunctionSymbol);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp, Error);
2021-04-12 18:19:14 +04:30
2021-06-27 19:48:25 +04:30
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, Op1Symbol);
PushSymbol(CodeBuffer, TempSymbol);
2021-04-12 18:19:14 +04:30
2021-06-27 19:48:25 +04:30
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
FreeTemp(Op1);
2022-05-18 13:26:57 +09:00
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-06-27 19:48:25 +04:30
}
else if (IsOneOperandOperator(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2022-05-18 23:44:03 +04:30
2021-06-27 19:48:25 +04:30
PushSymbol(CodeBuffer, Op0Symbol);
2021-04-12 18:19:14 +04:30
2021-06-27 19:48:25 +04:30
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
2022-05-18 13:26:57 +09:00
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-06-27 19:48:25 +04:30
}
else if (!strcmp(Operator->Value, "@VARGSTART"))
2021-04-12 18:19:14 +04:30
{
2022-05-07 22:51:55 +09:00
PTOKEN OperatorCopy = CopyToken(Operator);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, OperatorCopy);
2021-04-12 18:19:14 +04:30
}
2021-06-27 19:48:25 +04:30
else if (!strcmp(Operator->Value, "@START_OF_IF"))
{
2022-05-07 22:51:55 +09:00
PTOKEN OperatorCopy = CopyToken(Operator);
Push(MatchedStack, OperatorCopy);
2021-06-27 19:48:25 +04:30
}
else if (!strcmp(Operator->Value, "@JZ"))
{
// UINT64 CurrentPointer = CodeBuffer->Pointer;
2021-06-27 19:48:25 +04:30
PushSymbol(CodeBuffer, OperatorSymbol);
PSYMBOL JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_NUM_TYPE;
JumpAddressSymbol->Value = 0xffffffffffffffff;
PushSymbol(CodeBuffer, JumpAddressSymbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpAddressSymbol);
2021-06-27 19:48:25 +04:30
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2022-05-07 22:51:55 +09:00
2022-05-18 23:44:03 +04:30
PushSymbol(CodeBuffer, Op0Symbol);
2021-04-12 19:02:43 +04:30
2022-05-08 00:03:50 +09:00
char str[20] = {0};
2024-03-17 20:33:02 +09:00
sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer);
2022-05-07 22:51:55 +09:00
PTOKEN CurrentAddressToken = NewToken(DECIMAL, str);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, CurrentAddressToken);
2021-06-27 19:48:25 +04:30
FreeTemp(Op0);
2022-05-18 13:26:57 +09:00
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-06-27 19:48:25 +04:30
}
else if (!strcmp(Operator->Value, "@JMP_TO_END_AND_JZCOMPLETED"))
{
//
// Set JZ jump address
//
UINT64 CurrentPointer = CodeBuffer->Pointer;
2022-05-18 23:44:03 +04:30
PTOKEN JumpSemanticAddressToken = Pop(MatchedStack);
2021-06-27 19:48:25 +04:30
UINT64 JumpSemanticAddress = DecimalToInt(JumpSemanticAddressToken->Value);
2022-05-08 00:03:50 +09:00
PSYMBOL JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpSemanticAddress - 2);
2021-06-27 19:48:25 +04:30
JumpAddressSymbol->Value = CurrentPointer + 2;
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpSemanticAddressToken);
2021-06-27 19:48:25 +04:30
//
// Add jmp instruction to Code Buffer
//
PSYMBOL JumpInstruction = NewSymbol();
JumpInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JumpInstruction->Value = FUNC_JMP;
PushSymbol(CodeBuffer, JumpInstruction);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpInstruction);
2021-06-27 19:48:25 +04:30
//
// Add -1 decimal code to jump address
//
JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_NUM_TYPE;
JumpAddressSymbol->Value = 0xffffffffffffffff;
PushSymbol(CodeBuffer, JumpAddressSymbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpAddressSymbol);
2021-06-27 19:48:25 +04:30
//
// push current pointer to stack
//
2022-05-08 00:03:50 +09:00
char str[20] = {0};
2021-06-27 19:48:25 +04:30
sprintf(str, "%llu", CurrentPointer);
2022-05-07 22:51:55 +09:00
PTOKEN CurrentAddressToken = NewToken(DECIMAL, str);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, CurrentAddressToken);
}
else if (!strcmp(Operator->Value, "@END_OF_IF"))
{
2022-05-08 00:03:50 +09:00
UINT64 CurrentPointer = CodeBuffer->Pointer;
2022-05-18 23:44:03 +04:30
PTOKEN JumpSemanticAddressToken = Pop(MatchedStack);
2021-06-27 19:48:25 +04:30
PSYMBOL JumpAddressSymbol;
while (strcmp(JumpSemanticAddressToken->Value, "@START_OF_IF"))
{
UINT64 JumpSemanticAddress = DecimalToInt(JumpSemanticAddressToken->Value);
JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpSemanticAddress + 1);
2022-05-08 00:03:50 +09:00
JumpAddressSymbol->Value = CurrentPointer;
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpSemanticAddressToken);
2021-06-27 19:48:25 +04:30
JumpSemanticAddressToken = Pop(MatchedStack);
}
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpSemanticAddressToken);
2021-06-27 19:48:25 +04:30
}
else if (!strcmp(Operator->Value, "@START_OF_WHILE"))
{
//
// Push @START_OF_WHILE token into matched stack
//
2022-05-07 22:51:55 +09:00
PTOKEN OperatorCopy = CopyToken(Operator);
Push(MatchedStack, OperatorCopy);
2022-05-08 00:03:50 +09:00
char str[20] = {0};
2024-03-17 20:33:02 +09:00
sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer);
2022-05-18 23:44:03 +04:30
PTOKEN CurrentAddressToken = NewToken(DECIMAL, str);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, CurrentAddressToken);
}
else if (!strcmp(Operator->Value, "@START_OF_WHILE_COMMANDS"))
{
2022-05-08 00:03:50 +09:00
UINT64 CurrentPointer = CodeBuffer->Pointer;
2022-05-07 22:51:55 +09:00
PTOKEN JzToken = NewToken(SEMANTIC_RULE, "@JZ");
2022-05-19 20:16:57 +09:00
RemoveSymbol(&OperatorSymbol);
2021-06-27 19:48:25 +04:30
OperatorSymbol = ToSymbol(JzToken, Error);
2022-05-19 20:16:57 +09:00
RemoveToken(&JzToken);
2021-06-27 19:48:25 +04:30
PSYMBOL JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_NUM_TYPE;
JumpAddressSymbol->Value = 0xffffffffffffffff;
2021-06-27 19:48:25 +04:30
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2022-05-07 22:51:55 +09:00
PTOKEN StartOfWhileToken = Pop(MatchedStack);
2022-05-18 23:44:03 +04:30
char str[20];
2022-05-08 00:03:50 +09:00
sprintf(str, "%llu", CurrentPointer + 1);
2022-05-07 22:51:55 +09:00
PTOKEN CurrentAddressToken = NewToken(DECIMAL, str);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, CurrentAddressToken);
Push(MatchedStack, StartOfWhileToken);
PushSymbol(CodeBuffer, OperatorSymbol);
PushSymbol(CodeBuffer, JumpAddressSymbol);
2021-06-27 19:48:25 +04:30
PushSymbol(CodeBuffer, Op0Symbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpAddressSymbol);
2021-06-27 19:48:25 +04:30
FreeTemp(Op0);
2022-05-18 13:26:57 +09:00
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-06-27 19:48:25 +04:30
}
else if (!strcmp(Operator->Value, "@END_OF_WHILE"))
{
//
// Add jmp instruction to Code Buffer
//
PSYMBOL JumpInstruction = NewSymbol();
JumpInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JumpInstruction->Value = FUNC_JMP;
PushSymbol(CodeBuffer, JumpInstruction);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpInstruction);
2021-06-27 19:48:25 +04:30
//
// Add jmp address to Code buffer
//
2022-05-18 23:44:03 +04:30
PTOKEN JumpAddressToken = Pop(MatchedStack);
2021-06-27 19:48:25 +04:30
UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value);
PSYMBOL JumpAddressSymbol = ToSymbol(JumpAddressToken, Error);
2021-04-12 20:12:40 +04:30
2022-05-18 13:26:57 +09:00
PushSymbol(CodeBuffer, JumpAddressSymbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpAddressSymbol);
2021-06-27 19:48:25 +04:30
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-06-27 19:48:25 +04:30
//
// Set jumps addresses
//
2022-05-08 00:03:50 +09:00
UINT64 CurrentPointer = CodeBuffer->Pointer;
2021-04-12 20:12:40 +04:30
2021-06-27 19:48:25 +04:30
do
{
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpAddressToken);
2021-06-27 19:48:25 +04:30
JumpAddressToken = Pop(MatchedStack);
if (!strcmp(JumpAddressToken->Value, "@START_OF_WHILE"))
{
break;
}
JumpAddress = DecimalToInt(JumpAddressToken->Value);
JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpAddress);
JumpAddressSymbol->Value = CurrentPointer;
2021-04-12 20:12:40 +04:30
2021-06-27 19:48:25 +04:30
} while (TRUE);
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpAddressToken);
2021-06-27 19:48:25 +04:30
}
else if (!strcmp(Operator->Value, "@START_OF_DO_WHILE"))
{
//
// Push @START_OF_DO_WHILE token into matched stack
//
2022-05-07 22:51:55 +09:00
PTOKEN OperatorCopy = CopyToken(Operator);
Push(MatchedStack, OperatorCopy);
2021-04-13 22:53:02 +04:30
2022-05-18 23:44:03 +04:30
char str[20];
2024-03-17 20:33:02 +09:00
sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer);
2022-05-18 23:44:03 +04:30
PTOKEN CurrentAddressToken = NewToken(DECIMAL, str);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, CurrentAddressToken);
}
else if (!strcmp(Operator->Value, "@END_OF_DO_WHILE"))
{
//
// Add jmp instruction to Code Buffer
//
PSYMBOL JumpInstruction = NewSymbol();
JumpInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JumpInstruction->Value = FUNC_JNZ;
PushSymbol(CodeBuffer, JumpInstruction);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpInstruction);
2021-05-13 15:24:03 +04:30
2021-06-27 19:48:25 +04:30
//
// Add Op0 to CodeBuffer
//
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2021-05-13 15:24:03 +04:30
2021-06-27 19:48:25 +04:30
//
// Add jmp address to Code buffer
//
2022-05-18 23:44:03 +04:30
PTOKEN JumpAddressToken = Pop(MatchedStack);
2021-06-27 19:48:25 +04:30
UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value);
2021-06-27 19:48:25 +04:30
PSYMBOL JumpAddressSymbol = ToSymbol(JumpAddressToken, Error);
2021-06-27 19:48:25 +04:30
PushSymbol(CodeBuffer, JumpAddressSymbol);
PushSymbol(CodeBuffer, Op0Symbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpAddressSymbol);
2021-06-27 19:48:25 +04:30
FreeTemp(Op0);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-06-27 19:48:25 +04:30
//
// Set jumps addresses
//
2022-05-08 00:03:50 +09:00
UINT64 CurrentPointer = CodeBuffer->Pointer;
2021-06-27 19:48:25 +04:30
do
{
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpAddressToken);
2021-06-27 19:48:25 +04:30
JumpAddressToken = Pop(MatchedStack);
if (!strcmp(JumpAddressToken->Value, "@START_OF_DO_WHILE"))
{
break;
}
JumpAddress = DecimalToInt(JumpAddressToken->Value);
2022-03-19 03:05:07 +03:30
#ifdef _SCRIPT_ENGINE_LL1_DBG_EN
2021-06-27 19:48:25 +04:30
printf("Jz Jump Address = %d\n", JumpAddress);
2022-03-19 03:05:07 +03:30
#endif
2021-06-27 19:48:25 +04:30
JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpAddress);
JumpAddressSymbol->Value = CurrentPointer;
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
} while (TRUE);
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpAddressToken);
2021-06-27 19:48:25 +04:30
}
else if (!strcmp(Operator->Value, "@START_OF_FOR"))
{
//
// Push @START_OF_FOR token into matched stack
//
2022-05-07 22:51:55 +09:00
PTOKEN OperatorCopy = CopyToken(Operator);
Push(MatchedStack, OperatorCopy);
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Push current pointer into matched stack
//
2022-05-08 00:03:50 +09:00
char str[20] = {0};
2024-03-17 20:33:02 +09:00
sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer);
2022-05-07 22:51:55 +09:00
PTOKEN CurrentAddressToken = NewToken(DECIMAL, str);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, CurrentAddressToken);
}
else if (!strcmp(Operator->Value, "@FOR_INC_DEC"))
{
//
// JZ
//
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Add jz instruction to Code Buffer
//
PSYMBOL JnzInstruction = NewSymbol();
JnzInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JnzInstruction->Value = FUNC_JZ;
PushSymbol(CodeBuffer, JnzInstruction);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JnzInstruction);
2021-05-13 15:24:03 +04:30
2021-06-27 19:48:25 +04:30
//
2024-03-17 18:49:51 +09:00
// Add JZ address to Code CodeBuffer
2021-06-27 19:48:25 +04:30
//
PSYMBOL JnzAddressSymbol = NewSymbol();
JnzAddressSymbol->Type = SYMBOL_NUM_TYPE;
JnzAddressSymbol->Value = 0xffffffffffffffff;
PushSymbol(CodeBuffer, JnzAddressSymbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JnzAddressSymbol);
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Add Op0 to CodeBuffer
//
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
2022-05-18 23:44:03 +04:30
2022-05-18 13:26:57 +09:00
PushSymbol(CodeBuffer, Op0Symbol);
2021-06-27 19:48:25 +04:30
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
//
// JMP
//
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Add jmp instruction to Code Buffer
//
PSYMBOL JumpInstruction = NewSymbol();
JumpInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JumpInstruction->Value = FUNC_JMP;
PushSymbol(CodeBuffer, JumpInstruction);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpInstruction);
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
2024-03-17 18:49:51 +09:00
// Add jmp address to Code CodeBuffer
2021-06-27 19:48:25 +04:30
//
PSYMBOL JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_NUM_TYPE;
JumpAddressSymbol->Value = 0xffffffffffffffff;
PushSymbol(CodeBuffer, JumpAddressSymbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpAddressSymbol);
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Pop start_of_for address
//
2022-05-07 22:51:55 +09:00
PTOKEN StartOfForAddressToken = Pop(MatchedStack);
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Push current pointer into matched stack
//
2022-05-08 00:03:50 +09:00
char str[20] = {0};
2024-03-17 20:33:02 +09:00
sprintf(str, "%llu", (UINT64)CodeBuffer->Pointer);
2022-05-18 23:44:03 +04:30
PTOKEN CurrentAddressToken = NewToken(DECIMAL, str);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, CurrentAddressToken);
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Push start_of_for address to matched stack
//
Push(MatchedStack, StartOfForAddressToken);
}
else if (!strcmp(Operator->Value, "@START_OF_FOR_COMMANDS"))
{
//
// JMP
//
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Add jmp instruction to Code Buffer
//
PSYMBOL JumpInstruction = NewSymbol();
JumpInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JumpInstruction->Value = FUNC_JMP;
PushSymbol(CodeBuffer, JumpInstruction);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpInstruction);
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Add jmp address to Code buffer
//
2022-05-18 23:44:03 +04:30
PTOKEN JumpAddressToken = Pop(MatchedStack);
2021-06-27 19:48:25 +04:30
UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value);
2021-06-27 19:48:25 +04:30
PSYMBOL JumpAddressSymbol = ToSymbol(JumpAddressToken, Error);
2022-05-18 23:44:03 +04:30
2022-05-18 13:26:57 +09:00
PushSymbol(CodeBuffer, JumpAddressSymbol);
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpAddressToken);
RemoveSymbol(&JumpAddressSymbol);
2021-06-27 19:48:25 +04:30
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Set jmp address
//
2022-05-18 23:44:03 +04:30
UINT64 CurrentPointer = CodeBuffer->Pointer;
JumpAddressToken = Pop(MatchedStack);
JumpAddress = DecimalToInt(JumpAddressToken->Value);
2021-06-27 19:48:25 +04:30
JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpAddress - 1);
2022-05-08 00:03:50 +09:00
JumpAddressSymbol->Value = CurrentPointer;
2021-06-27 19:48:25 +04:30
//
// Push address of jz address to stack
//
2022-05-08 00:03:50 +09:00
char str[20] = {0};
2021-06-27 19:48:25 +04:30
sprintf(str, "%llu", JumpAddress - 4);
2022-05-07 22:51:55 +09:00
PTOKEN JzAddressToken = NewToken(DECIMAL, str);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, JzAddressToken);
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
2024-03-17 18:49:51 +09:00
// Push @INC_DEC token to matched stack
2021-06-27 19:48:25 +04:30
//
2022-05-07 22:51:55 +09:00
PTOKEN IncDecToken = NewToken(SEMANTIC_RULE, "@INC_DEC");
2021-06-27 19:48:25 +04:30
Push(MatchedStack, IncDecToken);
//
2024-03-17 18:49:51 +09:00
// Push start of inc_dec address to matched stack
2021-06-27 19:48:25 +04:30
//
Push(MatchedStack, JumpAddressToken);
}
else if (!strcmp(Operator->Value, "@END_OF_FOR"))
{
//
// Jmp
//
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Add jmp instruction to Code Buffer
//
PSYMBOL JumpInstruction = NewSymbol();
JumpInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JumpInstruction->Value = FUNC_JMP;
PushSymbol(CodeBuffer, JumpInstruction);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpInstruction);
2021-04-13 22:53:02 +04:30
2021-06-27 19:48:25 +04:30
//
// Add jmp address to Code buffer
//
2022-05-18 23:44:03 +04:30
PTOKEN JumpAddressToken = Pop(MatchedStack);
2021-06-27 19:48:25 +04:30
UINT64 JumpAddress = DecimalToInt(JumpAddressToken->Value);
2021-06-27 19:48:25 +04:30
PSYMBOL JumpAddressSymbol = ToSymbol(JumpAddressToken, Error);
2021-06-27 19:48:25 +04:30
PushSymbol(CodeBuffer, JumpAddressSymbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpAddressSymbol);
RemoveToken(&JumpAddressToken);
2021-06-27 19:48:25 +04:30
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-06-27 19:48:25 +04:30
JumpAddressToken = Pop(MatchedStack);
2021-06-27 19:48:25 +04:30
//
// Set jumps addresses
//
2022-05-08 00:03:50 +09:00
UINT64 CurrentPointer = CodeBuffer->Pointer;
2021-06-27 19:48:25 +04:30
do
{
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpAddressToken);
2021-06-27 19:48:25 +04:30
JumpAddressToken = Pop(MatchedStack);
if (!strcmp(JumpAddressToken->Value, "@START_OF_FOR"))
{
break;
}
else
{
JumpAddress = DecimalToInt(JumpAddressToken->Value);
2021-09-05 21:55:42 +09:00
2021-06-27 19:48:25 +04:30
JumpAddressSymbol = (PSYMBOL)(CodeBuffer->Head + JumpAddress);
JumpAddressSymbol->Value = CurrentPointer;
}
2021-06-27 19:48:25 +04:30
} while (TRUE);
2022-05-19 20:16:57 +09:00
RemoveToken(&JumpAddressToken);
2021-06-27 19:48:25 +04:30
}
else if (!strcmp(Operator->Value, "@BREAK"))
{
2021-06-27 19:48:25 +04:30
//
// Pop Objects from stack while reaching @START_OF_*
//
2022-05-08 01:00:24 +09:00
PTOKEN_LIST TempStack = NewTokenList();
2022-05-07 22:51:55 +09:00
PTOKEN TempToken;
2021-06-27 19:48:25 +04:30
do
{
2021-06-27 19:48:25 +04:30
TempToken = Pop(MatchedStack);
2021-06-27 19:48:25 +04:30
if ((!strcmp(TempToken->Value, "@START_OF_FOR")) ||
(!strcmp(TempToken->Value, "@START_OF_WHILE")) ||
(!strcmp(TempToken->Value, "@START_OF_DO_WHILE")))
{
//
// Push back START_OF_*
//
Push(MatchedStack, TempToken);
2021-06-27 19:48:25 +04:30
//
// Push current pointer into matched stack
//
2022-05-18 23:44:03 +04:30
UINT64 CurrentPointer = CodeBuffer->Pointer + 1;
2022-05-07 22:51:55 +09:00
char str[20];
2021-06-27 19:48:25 +04:30
sprintf(str, "%llu", CurrentPointer);
2022-05-18 23:44:03 +04:30
PTOKEN CurrentAddressToken = NewToken(DECIMAL, str);
2021-06-27 19:48:25 +04:30
Push(MatchedStack, CurrentAddressToken);
//
// JMP
//
//
// Add jmp instruction to Code Buffer
//
PSYMBOL JumpInstruction = NewSymbol();
JumpInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JumpInstruction->Value = FUNC_JMP;
PushSymbol(CodeBuffer, JumpInstruction);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpInstruction);
2021-06-27 19:48:25 +04:30
//
// Add jmp address to Code buffer
//
PSYMBOL JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_NUM_TYPE;
JumpAddressSymbol->Value = 0xffffffffffffffff;
PushSymbol(CodeBuffer, JumpAddressSymbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpAddressSymbol);
2021-06-27 19:48:25 +04:30
//
//
//
do
{
TempToken = Pop(TempStack);
Push(MatchedStack, TempToken);
2021-06-27 19:48:25 +04:30
} while (TempStack->Pointer != 0);
break;
}
else if (MatchedStack->Pointer == 0)
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
2022-05-19 20:16:57 +09:00
RemoveToken(&TempToken);
2021-06-27 19:48:25 +04:30
break;
}
else
{
Push(TempStack, TempToken);
}
2021-06-27 19:48:25 +04:30
} while (TRUE);
RemoveTokenList(TempStack);
}
else if (!strcmp(Operator->Value, "@CONTINUE"))
{
//
// Pop Objects from stack while reaching @INC_DEC
//
2022-05-08 01:00:24 +09:00
PTOKEN_LIST TempStack = NewTokenList();
2022-05-07 22:51:55 +09:00
PTOKEN TempToken;
2021-06-27 19:48:25 +04:30
do
{
TempToken = Pop(MatchedStack);
2021-06-27 19:48:25 +04:30
if (!strcmp(TempToken->Value, "@INC_DEC"))
{
2021-06-27 19:48:25 +04:30
//
// Push back INC_DEC
//
Push(MatchedStack, TempToken);
2021-06-27 19:48:25 +04:30
//
// Add jmp instruction to Code Buffer
//
PSYMBOL JumpInstruction = NewSymbol();
JumpInstruction->Type = SYMBOL_SEMANTIC_RULE_TYPE;
JumpInstruction->Value = FUNC_JMP;
PushSymbol(CodeBuffer, JumpInstruction);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpInstruction);
2021-06-27 19:48:25 +04:30
//
// Add jmp address to Code buffer
//
TempToken = Pop(TempStack);
Push(MatchedStack, TempToken);
2021-06-27 19:48:25 +04:30
PSYMBOL JumpAddressSymbol = NewSymbol();
JumpAddressSymbol->Type = SYMBOL_NUM_TYPE;
JumpAddressSymbol->Value = DecimalToInt(TempToken->Value);
PushSymbol(CodeBuffer, JumpAddressSymbol);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&JumpAddressSymbol);
2021-06-27 19:48:25 +04:30
//
//
//
do
{
TempToken = Pop(TempStack);
Push(MatchedStack, TempToken);
2021-06-27 19:48:25 +04:30
} while (TempStack->Pointer != 0);
break;
}
else if (MatchedStack->Pointer == 0)
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
else
{
Push(TempStack, TempToken);
}
2021-06-27 19:48:25 +04:30
} while (TRUE);
2021-06-27 19:48:25 +04:30
RemoveTokenList(TempStack);
}
else if (IsType9Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
Temp = NewTemp(Error, CurrentFunctionSymbol);
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp, Error);
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, TempSymbol);
FreeTemp(Op0);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
}
else if (IsType10Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
Op1 = Pop(MatchedStack);
Op1Symbol = ToSymbol(Op1, Error);
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, Op1Symbol);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
Temp = NewTemp(Error, CurrentFunctionSymbol);
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp, Error);
PushSymbol(CodeBuffer, TempSymbol);
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
FreeTemp(Op1);
}
else if (IsType11Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
Op1 = Pop(MatchedStack);
Op1Symbol = ToSymbol(Op1, Error);
PTOKEN Op2 = Pop(MatchedStack);
PSYMBOL Op2Symbol = ToSymbol(Op2, Error);
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, Op1Symbol);
PushSymbol(CodeBuffer, Op2Symbol);
Temp = NewTemp(Error, CurrentFunctionSymbol);
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp, Error);
PushSymbol(CodeBuffer, TempSymbol);
FreeTemp(Op2);
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
FreeTemp(Op1);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
}
else if (IsType12Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
Temp = NewTemp(Error, CurrentFunctionSymbol);
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp, Error);
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, TempSymbol);
FreeTemp(Op0);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
}
else if (IsType13Func(Operator))
{
PushSymbol(CodeBuffer, OperatorSymbol);
Op0 = Pop(MatchedStack);
Op0Symbol = ToSymbol(Op0, Error);
Op1 = Pop(MatchedStack);
Op1Symbol = ToSymbol(Op1, Error);
PushSymbol(CodeBuffer, Op0Symbol);
PushSymbol(CodeBuffer, Op1Symbol);
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
Temp = NewTemp(Error, CurrentFunctionSymbol);
Push(MatchedStack, Temp);
TempSymbol = ToSymbol(Temp, Error);
PushSymbol(CodeBuffer, TempSymbol);
//
// Free the operand if it is a temp value
//
FreeTemp(Op0);
FreeTemp(Op1);
}
2021-06-27 19:48:25 +04:30
else
{
*Error = SCRIPT_ENGINE_ERROR_UNHANDLED_SEMANTIC_RULE;
}
break;
}
2021-06-27 19:48:25 +04:30
#ifdef _SCRIPT_ENGINE_CODEGEN_DBG_EN
//
// Print Debug Info
//
printf("Semantic Stack:\n");
PrintTokenList(MatchedStack);
printf("\n");
2021-06-27 19:48:25 +04:30
printf("Code Buffer:\n");
PrintSymbolBuffer(CodeBuffer);
printf("------------------------------------------\n\n");
#endif
2022-05-08 00:03:50 +09:00
if (Op0)
2022-05-19 20:16:57 +09:00
RemoveToken(&Op0);
2022-05-08 00:03:50 +09:00
if (Op1)
2022-05-19 20:16:57 +09:00
RemoveToken(&Op1);
2021-06-27 19:48:25 +04:30
if (Op2)
2022-05-19 20:16:57 +09:00
RemoveToken(&Op2);
2022-05-19 20:16:57 +09:00
RemoveSymbol(&OperatorSymbol);
2021-06-27 19:48:25 +04:30
if (Op0Symbol)
2022-05-19 20:16:57 +09:00
RemoveSymbol(&Op0Symbol);
2021-06-27 19:48:25 +04:30
if (Op1Symbol)
2022-05-19 20:16:57 +09:00
RemoveSymbol(&Op1Symbol);
2021-06-27 19:48:25 +04:30
if (Op2Symbol)
2022-05-19 20:16:57 +09:00
RemoveSymbol(&Op2Symbol);
2021-06-27 19:48:25 +04:30
if (TempSymbol)
2022-05-19 20:16:57 +09:00
RemoveSymbol(&TempSymbol);
2020-11-29 23:09:39 +03:30
return;
2020-10-20 19:35:15 +03:30
}
2022-05-10 15:08:24 +04:30
/**
2022-05-18 16:00:16 +09:00
* @brief Computes the boolean expression length starting from the current input position
2023-01-18 20:23:40 +09:00
*
* @param str
* @param WaitForWaitStatementBooleanExpression
* @param CurrentIn
* @return UINT64
2022-05-10 15:08:24 +04:30
*/
UINT64
2022-05-07 22:51:55 +09:00
BooleanExpressionExtractEnd(char * str, BOOL * WaitForWaitStatementBooleanExpression, PTOKEN CurrentIn)
{
UINT64 BooleanExpressionSize = 0;
if (*WaitForWaitStatementBooleanExpression)
{
while (str[InputIdx + BooleanExpressionSize - 1] != ';')
{
BooleanExpressionSize += 1;
}
*WaitForWaitStatementBooleanExpression = FALSE;
return InputIdx + BooleanExpressionSize - 1;
}
else
{
int OpenParanthesesCount = 1;
if (!strcmp(CurrentIn->Value, "("))
{
OpenParanthesesCount++;
}
while (str[InputIdx + BooleanExpressionSize - 1] != '\0')
{
if (str[InputIdx + BooleanExpressionSize - 1] == ')')
{
OpenParanthesesCount--;
if (OpenParanthesesCount == 0)
{
return InputIdx + BooleanExpressionSize - 1;
}
}
else if (str[InputIdx + BooleanExpressionSize - 1] == '(')
{
OpenParanthesesCount++;
}
BooleanExpressionSize++;
}
}
return -1;
}
/**
2023-01-18 20:23:40 +09:00
* @brief LALR parser used for parsing boolean expression
*
* @param BooleanExpressionSize
* @param FirstToken
* @param MatchedStack
* @param CodeBuffer
* @param str
* @param c
* @param Error
2022-05-10 15:08:24 +04:30
*/
void
2021-04-11 18:27:23 +04:30
ScriptEngineBooleanExpresssionParse(
2021-06-27 19:48:25 +04:30
UINT64 BooleanExpressionSize,
2022-05-07 22:51:55 +09:00
PTOKEN FirstToken,
2022-05-18 23:44:03 +04:30
PTOKEN_LIST MatchedStack,
PSYMBOL_BUFFER UserDefinedFunctions,
2021-06-27 19:48:25 +04:30
PSYMBOL_BUFFER CodeBuffer,
char * str,
char * c,
PSCRIPT_ENGINE_ERROR_TYPE Error)
{
2022-05-08 01:00:24 +09:00
PTOKEN_LIST Stack = NewTokenList();
2022-05-07 22:51:55 +09:00
PTOKEN State = NewToken(STATE_ID, "0");
Push(Stack, State);
#ifdef _SCRIPT_ENGINE_LALR_DBG_EN
printf("Boolean Expression: ");
2022-05-08 10:53:39 +09:00
printf("%s", FirstToken->Value);
for (int i = InputIdx - 1; i < BooleanExpressionSize; i++)
{
2022-05-08 10:53:39 +09:00
printf("%c", str[i]);
}
printf("\n\n");
#endif
//
// End of File Token
//
2022-05-07 22:51:55 +09:00
PTOKEN EndToken = NewToken(END_OF_STACK, "$");
PTOKEN CurrentIn = CopyToken(FirstToken);
PTOKEN TopToken = NULL;
PTOKEN Lhs = NULL;
PTOKEN Temp = NULL;
PTOKEN Operand = NULL;
PTOKEN SemanticRule = NULL;
int Action = INVALID;
int StateId = 0;
int Goto = 0;
int InputPointer = 0;
int RhsSize = 0;
unsigned int InputIdxTemp;
char Ctemp;
while (1)
{
2021-04-11 18:27:23 +04:30
TopToken = Top(Stack);
int TerminalId = LalrGetTerminalId(CurrentIn);
StateId = (int)DecimalToSignedInt(TopToken->Value);
if (StateId == INVALID || TerminalId < 0)
2021-04-11 18:27:23 +04:30
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
2021-04-11 18:27:23 +04:30
}
Action = LalrActionTable[StateId][TerminalId];
2021-04-11 18:27:23 +04:30
2021-06-27 19:48:25 +04:30
#ifdef _SCRIPT_ENGINE_LALR_DBG_EN
2021-04-11 18:27:23 +04:30
printf("Stack :\n");
PrintTokenList(Stack);
2021-06-27 19:48:25 +04:30
printf("Action : %d\n\n", Action);
2021-04-11 18:27:23 +04:30
#endif
if (Action == LALR_ACCEPT)
{
2021-06-27 19:48:25 +04:30
*Error = SCRIPT_ENGINE_ERROR_FREE;
break;
}
if (Action == INVALID)
{
2021-06-27 19:48:25 +04:30
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
if (Action == 0)
{
*Error = SCRIPT_ENGINE_ERROR_SYNTAX;
break;
}
else if (Action >= 0) // Shift
{
StateId = Action;
Push(Stack, CurrentIn);
2022-05-08 00:03:50 +09:00
char buffer[20] = {0};
2022-05-07 22:51:55 +09:00
sprintf(buffer, "%d", StateId);
State = NewToken(STATE_ID, buffer);
Push(Stack, State);
InputIdxTemp = InputIdx;
Ctemp = *c;
2021-06-27 19:48:25 +04:30
CurrentIn = Scan(str, c);
if (InputIdx - 1 > BooleanExpressionSize)
{
InputIdx = InputIdxTemp;
*c = Ctemp;
2021-06-27 19:48:25 +04:30
2022-05-19 20:16:57 +09:00
RemoveToken(&CurrentIn);
2021-06-27 19:48:25 +04:30
2022-05-07 22:51:55 +09:00
CurrentIn = CopyToken(EndToken);
}
}
else if (Action < 0) // Reduce
{
2021-04-11 18:27:23 +04:30
StateId = -Action;
Lhs = (PTOKEN)&LalrLhs[StateId - 1];
2021-04-11 18:27:23 +04:30
RhsSize = LalrGetRhsSize(StateId - 1);
SemanticRule = (PTOKEN)&LalrSemanticRules[StateId - 1];
2021-04-11 18:27:23 +04:30
for (int i = 0; i < 2 * RhsSize; i++)
{
Temp = Pop(Stack);
2021-04-11 18:27:23 +04:30
if (SemanticRule->Type == SEMANTIC_RULE && !strcmp(SemanticRule->Value, "@PUSH"))
{
if (LalrIsOperandType(Temp))
{
Operand = Temp;
Push(MatchedStack, Operand);
}
else
{
2022-05-19 20:16:57 +09:00
RemoveToken(&Temp);
2021-04-11 18:27:23 +04:30
}
}
else
{
2022-05-19 20:16:57 +09:00
RemoveToken(&Temp);
}
}
2021-04-11 18:27:23 +04:30
if (SemanticRule->Type == SEMANTIC_RULE)
{
if (!strcmp(SemanticRule->Value, "@PUSH"))
{
}
else
{
CodeGen(MatchedStack, UserDefinedFunctions, CodeBuffer, SemanticRule, Error);
2021-06-27 19:48:25 +04:30
if (*Error != SCRIPT_ENGINE_ERROR_FREE)
{
break;
}
2021-04-11 18:27:23 +04:30
}
}
Temp = Top(Stack);
StateId = (int)DecimalToSignedInt(Temp->Value);
2021-04-11 18:27:23 +04:30
Goto = LalrGotoTable[StateId][LalrGetNonTerminalId(Lhs)];
2022-05-07 22:51:55 +09:00
PTOKEN LhsCopy = CopyToken(Lhs);
2021-06-27 19:48:25 +04:30
2022-05-08 00:03:50 +09:00
char buffer[20] = {0};
2022-05-07 22:51:55 +09:00
sprintf(buffer, "%d", Goto);
State = NewToken(STATE_ID, buffer);
2021-06-27 19:48:25 +04:30
Push(Stack, LhsCopy);
Push(Stack, State);
}
}
2021-06-27 19:48:25 +04:30
if (EndToken)
2022-05-19 20:16:57 +09:00
RemoveToken(&EndToken);
2021-06-27 19:48:25 +04:30
if (Stack)
RemoveTokenList(Stack);
if (CurrentIn)
2022-05-19 20:16:57 +09:00
RemoveToken(&CurrentIn);
return;
}
2022-05-10 15:08:24 +04:30
2020-10-20 19:35:15 +03:30
/**
2023-01-18 20:23:40 +09:00
* @brief Allocates a new SYMBOL and returns the reference to it
*
* @return PSYMBOL
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
PSYMBOL
NewSymbol(void)
2020-10-20 19:35:15 +03:30
{
PSYMBOL Symbol;
2024-03-17 20:33:02 +09:00
Symbol = (PSYMBOL)malloc(sizeof(SYMBOL));
if (Symbol == NULL)
{
//
// There was an error allocating buffer
//
return NULL;
}
Symbol->Value = 0;
Symbol->Len = 0;
Symbol->Type = 0;
Symbol->VariableType = 0;
2020-10-20 19:35:15 +03:30
return Symbol;
}
2022-05-10 15:08:24 +04:30
/**
2023-01-18 20:23:40 +09:00
* @brief Allocates a new SYMBOL with string type and returns the reference to it
*
* @param value
* @return PSYMBOL
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
PSYMBOL
NewStringSymbol(PTOKEN Token)
2020-12-03 20:54:33 +03:30
{
PSYMBOL Symbol;
int BufferSize = (3 * sizeof(unsigned long long) + Token->Len) / sizeof(SYMBOL) + 1;
2024-03-17 20:33:02 +09:00
Symbol = (PSYMBOL)calloc(sizeof(SYMBOL), BufferSize);
if (Symbol == NULL)
{
//
// There was an error allocating buffer
//
return NULL;
}
memcpy(&Symbol->Value, Token->Value, Token->Len);
2020-12-03 20:54:33 +03:30
SetType(&Symbol->Type, SYMBOL_STRING_TYPE);
Symbol->Len = Token->Len;
Symbol->VariableType = 0;
2020-12-03 20:54:33 +03:30
return Symbol;
}
/**
* @brief Allocates a new SYMBOL with wstring type and returns the reference to it
*
* @param value
* @return PSYMBOL
*/
PSYMBOL
NewWstringSymbol(PTOKEN Token)
{
PSYMBOL Symbol;
int BufferSize = (3 * sizeof(unsigned long long) + Token->Len) / sizeof(SYMBOL) + 1;
2024-03-17 20:33:02 +09:00
Symbol = (PSYMBOL)malloc(BufferSize * sizeof(SYMBOL));
if (Symbol == NULL)
{
//
// There was an error allocating buffer
//
return NULL;
}
memcpy(&Symbol->Value, Token->Value, Token->Len);
SetType(&Symbol->Type, SYMBOL_WSTRING_TYPE);
Symbol->Len = Token->Len;
Symbol->VariableType = 0;
return Symbol;
}
/**
* @brief
*
* @return PSYMBOL
*/
PSYMBOL
NewFunctionSymbol(char * FunctionName, VARIABLE_TYPE * VariableType)
{
2024-03-17 20:33:02 +09:00
int Length = (int)strlen(FunctionName);
PSYMBOL Symbol = NewSymbol();
Symbol = (PSYMBOL)malloc(sizeof(SYMBOL));
2024-03-17 20:33:02 +09:00
if (Symbol == NULL)
{
//
// There was an error allocating buffer
//
free(Symbol);
2024-03-17 20:33:02 +09:00
return NULL;
}
Symbol->Value = (unsigned long long)calloc(Length + 1, sizeof(char));
if (Symbol->Value == 0ull)
2024-03-17 20:33:02 +09:00
{
//
// There was an error allocating buffer
//
free(Symbol);
2024-03-17 20:33:02 +09:00
return NULL;
}
memcpy((void *)Symbol->Value, FunctionName, Length);
Symbol->Len = Length;
Symbol->Type = SYMBOL_USER_DEFINED_FUNCTION_TYPE;
2024-03-17 20:48:07 +09:00
Symbol->VariableType = (long long unsigned)VariableType;
return Symbol;
}
/**
* @brief
*
* @return PSYMBOL
*/
2022-05-10 15:08:24 +04:30
/**
* @brief Returns the number of SYMBOL objects (24 bytes) allocated by string or wstring sybmol
2023-01-18 20:23:40 +09:00
*
* @param Symbol
* @return unsigned int
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
unsigned int
GetSymbolHeapSize(PSYMBOL Symbol)
2020-12-03 21:21:35 +03:30
{
int Temp = (3 * sizeof(unsigned long long) + (int)Symbol->Len) / sizeof(SYMBOL) + 1;
2020-12-03 21:21:35 +03:30
return Temp;
}
2020-10-20 19:35:15 +03:30
/**
2022-05-18 16:00:16 +09:00
* @brief Frees the memory allocate by this Symbol
2023-01-18 20:23:40 +09:00
*
* @param Symbol
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
void
2022-05-31 17:09:25 +04:30
RemoveSymbol(PSYMBOL * Symbol)
2020-10-20 19:35:15 +03:30
{
2022-05-19 20:16:57 +09:00
free(*Symbol);
*Symbol = NULL;
2020-10-20 19:35:15 +03:30
return;
}
/**
2022-05-18 16:00:16 +09:00
* @brief Prints symbol
2023-01-18 20:23:40 +09:00
*
* @param Symbol
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
void
PrintSymbol(PSYMBOL Symbol)
2020-10-20 19:35:15 +03:30
{
2020-12-03 21:21:35 +03:30
if (Symbol->Type == SYMBOL_STRING_TYPE)
{
2024-03-17 20:48:07 +09:00
printf("Type:%llx, Value:0x%p\n", Symbol->Type, &Symbol->Value);
2020-12-03 21:21:35 +03:30
}
else
{
printf("Type:%llx, Value:0x%llx\n", Symbol->Type, Symbol->Value);
}
2020-10-20 19:35:15 +03:30
}
2022-05-10 15:08:24 +04:30
/**
2022-05-18 16:00:16 +09:00
* @brief Converts Token to Symbol and returns the reference to it
2023-01-18 20:23:40 +09:00
*
* @param Token
* @param Error
* @return PSYMBOL
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
PSYMBOL
2022-05-07 22:51:55 +09:00
ToSymbol(PTOKEN Token, PSCRIPT_ENGINE_ERROR_TYPE Error)
2020-10-20 19:35:15 +03:30
{
PSYMBOL Symbol = NewSymbol();
switch (Token->Type)
{
case GLOBAL_ID:
Symbol->Value = GetGlobalIdentifierVal(Token);
SetType(&Symbol->Type, SYMBOL_GLOBAL_ID_TYPE);
return Symbol;
case LOCAL_ID:
Symbol->Value = GetLocalIdentifierVal(Token);
SetType(&Symbol->Type, SYMBOL_LOCAL_ID_TYPE);
2020-10-20 19:35:15 +03:30
return Symbol;
2020-10-20 19:35:15 +03:30
case DECIMAL:
Symbol->Value = DecimalToInt(Token->Value);
SetType(&Symbol->Type, SYMBOL_NUM_TYPE);
return Symbol;
2020-10-20 19:35:15 +03:30
case HEX:
Symbol->Value = HexToInt(Token->Value);
SetType(&Symbol->Type, SYMBOL_NUM_TYPE);
return Symbol;
2020-10-20 19:35:15 +03:30
case OCTAL:
Symbol->Value = OctalToInt(Token->Value);
SetType(&Symbol->Type, SYMBOL_NUM_TYPE);
return Symbol;
2020-10-20 19:35:15 +03:30
case BINARY:
Symbol->Value = BinaryToInt(Token->Value);
SetType(&Symbol->Type, SYMBOL_NUM_TYPE);
return Symbol;
case REGISTER:
2020-12-03 20:54:33 +03:30
Symbol->Value = RegisterToInt(Token->Value);
2020-10-20 19:35:15 +03:30
SetType(&Symbol->Type, SYMBOL_REGISTER_TYPE);
return Symbol;
case PSEUDO_REGISTER:
2020-12-03 20:54:33 +03:30
Symbol->Value = PseudoRegToInt(Token->Value);
2020-10-20 19:35:15 +03:30
SetType(&Symbol->Type, SYMBOL_PSEUDO_REG_TYPE);
return Symbol;
case SEMANTIC_RULE:
2021-03-22 18:19:39 +04:30
Symbol->Value = SemanticRuleToInt(Token->Value);
2020-10-20 19:35:15 +03:30
SetType(&Symbol->Type, SYMBOL_SEMANTIC_RULE_TYPE);
return Symbol;
2020-10-20 19:35:15 +03:30
case TEMP:
2021-03-22 18:19:39 +04:30
Symbol->Value = DecimalToInt(Token->Value);
2020-12-02 18:11:03 +03:30
SetType(&Symbol->Type, SYMBOL_TEMP_TYPE);
2020-10-20 19:35:15 +03:30
return Symbol;
case STACK_TEMP:
Symbol->Value = DecimalToInt(Token->Value);
SetType(&Symbol->Type, SYMBOL_STACK_TEMP_TYPE);
return Symbol;
2020-12-03 20:54:33 +03:30
case STRING:
2022-05-19 20:16:57 +09:00
RemoveSymbol(&Symbol);
return NewStringSymbol(Token);
2020-12-03 20:54:33 +03:30
case WSTRING:
RemoveSymbol(&Symbol);
return NewWstringSymbol(Token);
case FUNCTION_PARAMETER_ID:
Symbol->Value = GetFunctionParameterIdentifier(Token);
SetType(&Symbol->Type, SYMBOL_FUNCTION_PARAMETER_ID_TYPE);
return Symbol;
2020-10-20 19:35:15 +03:30
default:
2022-05-18 23:44:03 +04:30
*Error = SCRIPT_ENGINE_ERROR_UNRESOLVED_VARIABLE;
2022-05-18 13:26:57 +09:00
Symbol->Type = INVALID;
Symbol->Value = INVALID;
return Symbol;
2020-10-20 19:35:15 +03:30
}
}
2020-12-02 02:32:49 +03:30
/**
2023-01-18 20:23:40 +09:00
* @brief allocates a new Symbol Buffer and returns the reference to it
*
* @return PSYMBOL_BUFFER
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
PSYMBOL_BUFFER
NewSymbolBuffer(void)
2020-10-20 19:35:15 +03:30
{
2020-12-02 02:32:49 +03:30
PSYMBOL_BUFFER SymbolBuffer;
2024-03-17 20:33:02 +09:00
SymbolBuffer = (PSYMBOL_BUFFER)malloc(sizeof(*SymbolBuffer));
if (SymbolBuffer == NULL)
{
//
// There was an error allocating buffer
//
return NULL;
}
2020-12-02 02:32:49 +03:30
SymbolBuffer->Pointer = 0;
2021-03-22 18:19:39 +04:30
SymbolBuffer->Size = SYMBOL_BUFFER_INIT_SIZE;
SymbolBuffer->Head = (PSYMBOL)malloc(SymbolBuffer->Size * sizeof(SYMBOL));
2020-12-02 02:32:49 +03:30
SymbolBuffer->Message = NULL;
return SymbolBuffer;
2020-10-20 19:35:15 +03:30
}
2020-12-02 02:32:49 +03:30
/**
2023-01-18 20:23:40 +09:00
* @brief Frees the memory allocated by SymbolBuffer
*
* @param SymbolBuffer
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
void
RemoveSymbolBuffer(PSYMBOL_BUFFER SymbolBuffer)
2020-10-20 19:35:15 +03:30
{
free(SymbolBuffer->Message);
2020-12-02 02:32:49 +03:30
free(SymbolBuffer->Head);
free(SymbolBuffer);
2020-10-20 19:35:15 +03:30
}
2020-12-02 02:32:49 +03:30
/**
2022-05-18 16:00:16 +09:00
* @brief Gets a symbol and push it into the symbol buffer
2023-01-18 20:23:40 +09:00
*
* @param SymbolBuffer
* @param Symbol
* @return PSYMBOL_BUFFER
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
PSYMBOL_BUFFER
PushSymbol(PSYMBOL_BUFFER SymbolBuffer, const PSYMBOL Symbol)
2020-10-20 19:35:15 +03:30
{
2020-12-02 02:32:49 +03:30
//
// Calculate address to write new token
//
2021-03-22 18:19:39 +04:30
uintptr_t Head = (uintptr_t)SymbolBuffer->Head;
uintptr_t Pointer = (uintptr_t)SymbolBuffer->Pointer;
PSYMBOL WriteAddr = (PSYMBOL)(Head + Pointer * sizeof(SYMBOL));
2020-12-02 02:32:49 +03:30
if (Symbol->Type == SYMBOL_STRING_TYPE || Symbol->Type == SYMBOL_WSTRING_TYPE)
2021-03-22 18:19:39 +04:30
{
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
// Update Pointer
//
SymbolBuffer->Pointer += GetSymbolHeapSize(Symbol);
2020-12-03 20:54:33 +03:30
//
// Handle Overflow
//
2021-03-02 02:48:41 +03:30
if (SymbolBuffer->Pointer >= SymbolBuffer->Size - 1)
2020-12-03 20:54:33 +03:30
{
2021-03-02 02:48:41 +03:30
//
// Calculate new size for the symbol B
//
2024-03-17 20:33:02 +09:00
unsigned int NewSize = SymbolBuffer->Size;
2021-03-02 02:48:41 +03:30
do
{
2021-03-22 18:19:39 +04:30
NewSize *= 2;
2021-03-11 18:27:29 +03:30
} while (NewSize <= SymbolBuffer->Pointer);
2021-03-02 02:48:41 +03:30
2020-12-03 20:54:33 +03:30
//
// Allocate a new buffer for string list with doubled length
//
2021-03-02 02:48:41 +03:30
PSYMBOL NewHead = (PSYMBOL)malloc(NewSize * sizeof(SYMBOL));
2020-12-03 20:54:33 +03:30
if (NewHead == NULL)
{
printf("err, could not allocate buffer");
return NULL;
}
2020-12-03 20:54:33 +03:30
//
2021-03-02 02:48:41 +03:30
// Copy old buffer to new buffer
2020-12-03 20:54:33 +03:30
//
memcpy(NewHead, SymbolBuffer->Head, SymbolBuffer->Size * sizeof(SYMBOL));
//
2021-03-02 02:48:41 +03:30
// Free old buffer
2020-12-03 20:54:33 +03:30
//
free(SymbolBuffer->Head);
//
2024-03-17 18:49:51 +09:00
// Update Head and size of SymbolBuffer
2020-12-03 20:54:33 +03:30
//
2021-03-02 02:48:41 +03:30
SymbolBuffer->Size = NewSize;
2020-12-03 20:54:33 +03:30
SymbolBuffer->Head = NewHead;
2021-03-02 02:48:41 +03:30
}
2021-03-22 18:19:39 +04:30
WriteAddr = (PSYMBOL)((uintptr_t)SymbolBuffer->Head + (uintptr_t)Pointer * (uintptr_t)sizeof(SYMBOL));
2021-03-02 02:48:41 +03:30
WriteAddr->Type = Symbol->Type;
WriteAddr->Len = Symbol->Len;
memcpy((char *)&WriteAddr->Value, (char *)&Symbol->Value, Symbol->Len);
2020-12-03 20:54:33 +03:30
}
else
{
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
// Write input to the appropriate address in SymbolBuffer
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
*WriteAddr = *Symbol;
2021-02-12 03:12:01 +03:30
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
// Update Pointer
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
SymbolBuffer->Pointer++;
2020-12-02 02:32:49 +03:30
//
2020-12-03 20:54:33 +03:30
// Handle Overflow
2020-12-02 02:32:49 +03:30
//
2023-11-21 06:34:20 +08:00
if (Pointer >= SymbolBuffer->Size - 1)
2020-12-03 20:54:33 +03:30
{
//
// Allocate a new buffer for string list with doubled length
//
PSYMBOL NewHead = (PSYMBOL)malloc(2 * SymbolBuffer->Size * sizeof(SYMBOL));
2020-12-02 02:32:49 +03:30
2024-03-17 20:33:02 +09:00
if (NewHead == NULL)
{
printf("err, could not allocate buffer");
return NULL;
}
2020-12-03 20:54:33 +03:30
//
// Copy old Buffer to new buffer
//
memcpy(NewHead, SymbolBuffer->Head, SymbolBuffer->Size * sizeof(SYMBOL));
2020-12-02 02:32:49 +03:30
2020-12-03 20:54:33 +03:30
//
// Free Old buffer
//
free(SymbolBuffer->Head);
//
2024-03-17 18:49:51 +09:00
// Update Head and size of SymbolBuffer
2020-12-03 20:54:33 +03:30
//
SymbolBuffer->Size *= 2;
SymbolBuffer->Head = NewHead;
}
2020-10-20 19:35:15 +03:30
}
2020-12-02 02:32:49 +03:30
2020-12-03 20:54:33 +03:30
return SymbolBuffer;
2020-10-20 19:35:15 +03:30
}
2020-12-02 02:32:49 +03:30
/**
2022-05-18 16:00:16 +09:00
* @brief Prints a symbol buffer
2023-01-18 20:23:40 +09:00
*
* @param SymbolBuffer
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
void
PrintSymbolBuffer(const PSYMBOL_BUFFER SymbolBuffer)
2020-10-20 19:35:15 +03:30
{
2020-12-02 02:32:49 +03:30
PSYMBOL Symbol;
2024-03-17 20:33:02 +09:00
for (unsigned int i = 0; i < SymbolBuffer->Pointer;)
2020-10-20 19:35:15 +03:30
{
2020-12-02 02:32:49 +03:30
Symbol = SymbolBuffer->Head + i;
2021-03-22 18:19:39 +04:30
2021-04-12 18:19:14 +04:30
printf("%8x:", i);
2020-12-02 02:32:49 +03:30
PrintSymbol(Symbol);
if (Symbol->Type == SYMBOL_STRING_TYPE || Symbol->Type == SYMBOL_WSTRING_TYPE)
2020-12-03 21:21:35 +03:30
{
int temp = GetSymbolHeapSize(Symbol);
2021-01-14 13:36:57 +03:30
i += temp;
2020-12-03 21:21:35 +03:30
}
else
{
i++;
}
2020-10-20 19:35:15 +03:30
}
}
2022-05-10 15:08:24 +04:30
/**
2022-05-18 16:00:16 +09:00
* @brief Converts register string to integer
2023-01-18 20:23:40 +09:00
*
* @param str
* @return unsigned long long int
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
unsigned long long int
RegisterToInt(char * str)
2020-10-20 19:35:15 +03:30
{
2020-12-02 18:11:03 +03:30
for (int i = 0; i < REGISTER_MAP_LIST_LENGTH; i++)
2020-10-22 13:53:31 +03:30
{
2020-12-02 18:11:03 +03:30
if (!strcmp(str, RegisterMapList[i].Name))
{
return RegisterMapList[i].Type;
}
2020-10-22 13:53:31 +03:30
}
2020-10-20 19:35:15 +03:30
return INVALID;
}
2022-05-10 15:08:24 +04:30
/**
2022-05-18 16:00:16 +09:00
* @brief Converts pseudo register string to integer
2023-01-18 20:23:40 +09:00
*
* @param str
* @return unsigned long long int
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
unsigned long long int
PseudoRegToInt(char * str)
2020-10-20 19:35:15 +03:30
{
2020-12-02 18:11:03 +03:30
for (int i = 0; i < PSEUDO_REGISTER_MAP_LIST_LENGTH; i++)
2020-10-22 13:53:31 +03:30
{
2020-12-02 18:11:03 +03:30
if (!strcmp(str, PseudoRegisterMapList[i].Name))
{
return PseudoRegisterMapList[i].Type;
}
2020-10-22 13:53:31 +03:30
}
2020-10-20 19:35:15 +03:30
return INVALID;
}
2022-05-10 15:08:24 +04:30
/**
2023-01-18 20:23:40 +09:00
* @brief Converts a sematinc rule token to integer
*
* @param str
* @return unsigned long long int
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
unsigned long long int
SemanticRuleToInt(char * str)
2020-10-20 19:35:15 +03:30
{
2020-12-02 18:11:03 +03:30
for (int i = 0; i < SEMANTIC_RULES_MAP_LIST_LENGTH; i++)
2020-10-28 12:29:30 +03:30
{
2020-12-02 18:11:03 +03:30
if (!strcmp(str, SemanticRulesMapList[i].Name))
{
return SemanticRulesMapList[i].Type;
}
2020-10-28 12:29:30 +03:30
}
2020-12-02 18:11:03 +03:30
return INVALID;
2020-10-20 19:35:15 +03:30
}
2022-05-10 15:08:24 +04:30
/**
2023-01-18 20:23:40 +09:00
* @brief Prints some information about the error
*
* @param Error
* @param str
* @return char*
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
char *
2021-06-27 19:48:25 +04:30
HandleError(PSCRIPT_ENGINE_ERROR_TYPE Error, char * str)
2020-12-03 18:02:49 +03:30
{
//
2022-03-19 03:05:07 +03:30
// calculate position of current line
//
unsigned int LineEnd;
for (int i = InputIdx;; i++)
{
if (str[i] == '\n' || str[i] == '\0')
{
LineEnd = i;
break;
}
}
2022-03-19 03:05:07 +03:30
2020-12-03 18:02:49 +03:30
//
// allocate required memory for message, 16 for line, 100 for error information,
// (CurrentTokenIdx - CurrentLineIdx) for space and,
// (LineEnd - CurrentLineIdx) for input string
2021-03-22 18:19:39 +04:30
//
int MessageSize = 16 + 100 + (CurrentTokenIdx - CurrentLineIdx) + (LineEnd - CurrentLineIdx);
2021-03-22 18:19:39 +04:30
char * Message = (char *)malloc(MessageSize);
2024-03-17 20:33:02 +09:00
if (Message == NULL)
{
printf("err, could not allocate buffer");
return NULL;
}
2021-03-22 18:19:39 +04:30
//
// add line number
2020-12-03 18:02:49 +03:30
//
strcpy(Message, "Line ");
char Line[16] = {0};
2020-12-03 18:02:49 +03:30
sprintf(Line, "%d:\n", CurrentLine);
strcat(Message, Line);
2020-12-03 18:02:49 +03:30
//
2021-03-22 18:19:39 +04:30
// add the line which error happened at
2020-12-03 18:02:49 +03:30
//
strncat(Message, (str + CurrentLineIdx), LineEnd - CurrentLineIdx);
2020-12-03 18:02:49 +03:30
strcat(Message, "\n");
2021-03-22 18:19:39 +04:30
//
// add pointer
2020-12-03 18:02:49 +03:30
//
char Space = ' ';
2022-05-08 11:14:46 +09:00
int n = (CurrentTokenIdx - CurrentLineIdx);
for (int i = 0; i < n; i++)
2020-12-03 18:02:49 +03:30
{
2021-03-22 18:19:39 +04:30
strncat(Message, &Space, 1);
}
2020-12-03 18:02:49 +03:30
strcat(Message, "^\n");
//
2021-03-22 18:19:39 +04:30
// add error cause and details
2020-12-03 18:02:49 +03:30
//
2021-06-27 19:48:25 +04:30
switch (*Error)
2020-12-03 18:02:49 +03:30
{
2021-06-27 19:48:25 +04:30
case SCRIPT_ENGINE_ERROR_SYNTAX:
2021-10-09 02:14:36 +03:30
strcat(Message, "Syntax Error: ");
2020-12-03 18:02:49 +03:30
strcat(Message, "Invalid Syntax");
return Message;
case SCRIPT_ENGINE_ERROR_UNKNOWN_TOKEN:
2021-10-09 02:14:36 +03:30
strcat(Message, "Syntax Error: ");
2021-06-27 19:48:25 +04:30
strcat(Message, "Unknown Token");
return Message;
case SCRIPT_ENGINE_ERROR_UNRESOLVED_VARIABLE:
2021-10-09 02:14:36 +03:30
strcat(Message, "Syntax Error: ");
2021-06-27 19:48:25 +04:30
strcat(Message, "Unresolved Variable");
return Message;
case SCRIPT_ENGINE_ERROR_UNHANDLED_SEMANTIC_RULE:
2021-10-09 02:14:36 +03:30
strcat(Message, "Syntax Error: ");
2021-06-27 19:48:25 +04:30
strcat(Message, "Unhandled Semantic Rule");
2020-12-03 18:02:49 +03:30
return Message;
2022-03-19 03:05:07 +03:30
case SCRIPT_ENGINE_ERROR_TEMP_LIST_FULL:
strcat(Message, "Internal Error: ");
strcat(Message, "Please split the expression to many smaller expressions.");
return Message;
case SCRIPT_ENGINE_ERROR_UNDEFINED_FUNCTION:
strcat(Message, "Undefined Function");
return Message;
case SCRIPT_ENGINE_ERROR_UNDEFINED_VARIABLE_TYPE:
strcat(Message, "Undefined Variable Type");
return Message;
case SCRIPT_ENGINE_ERROR_VOID_FUNCTION_RETURNING_VALUE:
strcat(Message, "Returning a value in void function");
return Message;
case SCRIPT_ENGINE_ERROR_NON_VOID_FUNCTION_NOT_RETURNING_VALUE:
strcat(Message, "Not returning a value in noo-void function");
return Message;
2020-12-03 18:02:49 +03:30
default:
2024-03-17 18:49:51 +09:00
strcat(Message, "Unknown Error: ");
2020-12-03 18:02:49 +03:30
return Message;
}
2021-03-03 16:53:19 +03:30
}
2022-05-10 15:08:24 +04:30
/**
2023-01-18 20:23:40 +09:00
* @brief Returns the integer assigned to global variable
*
* @param Token
* @return int
2022-05-10 15:08:24 +04:30
*/
2021-03-22 18:19:39 +04:30
int
2022-05-07 22:51:55 +09:00
GetGlobalIdentifierVal(PTOKEN Token)
2021-03-03 16:53:19 +03:30
{
2022-05-07 22:51:55 +09:00
PTOKEN CurrentToken;
2021-03-03 16:53:19 +03:30
for (uintptr_t i = 0; i < IdTable->Pointer; i++)
{
CurrentToken = *(IdTable->Head + i);
if (!strcmp(Token->Value, CurrentToken->Value))
{
return (int)i;
}
}
2021-06-27 19:48:25 +04:30
return -1;
}
2021-04-11 18:27:23 +04:30
2022-05-10 15:08:24 +04:30
/**
2022-05-18 16:00:16 +09:00
* @brief Returns the integer assigned to local variable
2023-01-18 20:23:40 +09:00
*
* @param Token
* @return int
2022-05-10 15:08:24 +04:30
*/
2021-06-27 19:48:25 +04:30
int
2022-05-07 22:51:55 +09:00
GetLocalIdentifierVal(PTOKEN Token)
{
2022-05-07 22:51:55 +09:00
PTOKEN CurrentToken;
for (uintptr_t i = 0; i < IdTable->Pointer; i++)
{
CurrentToken = *(IdTable->Head + i);
if (!strcmp(Token->Value, CurrentToken->Value))
{
return (int)i;
}
}
return -1;
}
2022-05-10 15:08:24 +04:30
/**
2024-03-17 18:49:51 +09:00
* @brief Allocates a new global variable and returns the integer assigned to it
2023-01-18 20:23:40 +09:00
*
* @param Token
* @return int
2022-05-10 15:08:24 +04:30
*/
int
2022-05-07 22:51:55 +09:00
NewGlobalIdentifier(PTOKEN Token)
2021-06-27 19:48:25 +04:30
{
2022-05-07 22:51:55 +09:00
PTOKEN CopiedToken = CopyToken(Token);
IdTable = Push(IdTable, CopiedToken);
2021-03-03 16:53:19 +03:30
return IdTable->Pointer - 1;
}
2021-04-11 18:27:23 +04:30
2022-05-10 15:08:24 +04:30
/**
2023-01-18 20:23:40 +09:00
* @brief Allocates a new local variable and returns the integer assigned to it
*
* @param Token
* @return int
2022-05-10 15:08:24 +04:30
*/
int
2022-05-07 22:51:55 +09:00
NewLocalIdentifier(PTOKEN Token)
{
2022-05-07 22:51:55 +09:00
PTOKEN CopiedToken = CopyToken(Token);
2022-05-18 23:44:03 +04:30
IdTable = Push(IdTable, CopiedToken);
return IdTable->Pointer - 1;
}
/**
* @brief
*
* @param Token
* @return int
*/
int
NewFunctionParameterIdentifier(PTOKEN Token)
{
PTOKEN CopiedToken = CopyToken(Token);
FunctionParameterIdTable = Push(FunctionParameterIdTable, CopiedToken);
return FunctionParameterIdTable->Pointer - 1;
}
/**
* @brief
*
* @param Token
* @return int
*/
int
GetFunctionParameterIdentifier(PTOKEN Token)
{
PTOKEN CurrentToken;
for (uintptr_t i = 0; i < FunctionParameterIdTable->Pointer; i++)
{
CurrentToken = *(FunctionParameterIdTable->Head + i);
if (!strcmp(Token->Value, CurrentToken->Value))
{
return (int)i;
}
}
return -1;
}
2022-05-10 15:08:24 +04:30
/**
2023-01-18 20:23:40 +09:00
* @brief Returns the size of Right Hand Side (RHS) of a rule
*
* @param RuleId
* @return int
2022-05-10 15:08:24 +04:30
*/
2021-04-11 18:27:23 +04:30
int
LalrGetRhsSize(int RuleId)
{
int Counter = 0;
int N = LalrRhsSize[RuleId];
for (int i = 0; i < N; i++)
{
if (LalrRhs[RuleId][i].Type != EPSILON && LalrRhs[RuleId][i].Type != SEMANTIC_RULE)
{
Counter++;
}
}
return Counter;
}
2022-05-10 15:08:24 +04:30
/**
2023-01-18 20:23:40 +09:00
* @brief Returns TRUE if the Token can be the operand of an operator
*
* @param Token
* @return BOOL
2022-05-10 15:08:24 +04:30
*/
2021-04-11 18:27:23 +04:30
BOOL
2022-05-07 22:51:55 +09:00
LalrIsOperandType(PTOKEN Token)
2021-04-11 18:27:23 +04:30
{
if (Token->Type == GLOBAL_ID)
{
return TRUE;
}
else if (Token->Type == GLOBAL_UNRESOLVED_ID)
{
return TRUE;
}
if (Token->Type == LOCAL_ID)
2021-04-11 18:27:23 +04:30
{
return TRUE;
}
else if (Token->Type == LOCAL_UNRESOLVED_ID)
2021-06-27 19:48:25 +04:30
{
return TRUE;
}
else if (Token->Type == FUNCTION_PARAMETER_ID)
{
return TRUE;
}
2021-04-11 18:27:23 +04:30
else if (Token->Type == DECIMAL)
{
return TRUE;
}
else if (Token->Type == HEX)
{
return TRUE;
}
else if (Token->Type == OCTAL)
{
return TRUE;
}
else if (Token->Type == BINARY)
{
return TRUE;
}
else if (Token->Type == REGISTER)
{
return TRUE;
}
else if (Token->Type == PSEUDO_REGISTER)
{
return TRUE;
}
else if (Token->Type == TEMP)
{
return TRUE;
}
else if (Token->Type == STRING)
{
return TRUE;
}
else if (Token->Type == WSTRING)
{
return TRUE;
}
2021-04-11 18:27:23 +04:30
return FALSE;
}
PSYMBOL_BUFFER
GetStackBuffer()
{
PSYMBOL_BUFFER StackBuffer = NewSymbolBuffer();
for (int i = 0; i < 128; i++)
{
PushSymbol(StackBuffer, NewSymbol());
}
return StackBuffer;
2024-03-17 18:49:51 +09:00
}