mirror of
https://github.com/suchmememanyskill/TegraExplorer.git
synced 2024-11-29 15:22:09 +00:00
963987d639
- Add a function to reboot to payload - Add an "Empty array" variable type that is created when you try to assign []. This will get filled with a valid entry upon first addition - Adds operator string array plus string
502 lines
No EOL
19 KiB
C
502 lines
No EOL
19 KiB
C
#include "args.h"
|
|
#include "types.h"
|
|
#include "functions.h"
|
|
#include "variables.h"
|
|
#include <string.h>
|
|
#include <mem/heap.h>
|
|
#include "../utils/utils.h"
|
|
|
|
char* utils_copyStringSize(const char* in, int size) {
|
|
if (size > strlen(in) || size < 0)
|
|
size = strlen(in);
|
|
|
|
char* out = calloc(size + 1, 1);
|
|
//strncpy(out, in, size);
|
|
if (size)
|
|
memcpy(out, in, size);
|
|
return out;
|
|
}
|
|
|
|
// do not include first openToken!
|
|
int distanceBetweenTokens(lexarToken_t* tokens, u32 len, int openToken, int closeToken) {
|
|
int i = 0;
|
|
int layer = 0;
|
|
for (; i < len; i++) {
|
|
if (tokens[i].token == openToken)
|
|
layer++;
|
|
else if (tokens[i].token == closeToken) {
|
|
if (layer == 0)
|
|
return i;
|
|
layer--;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
Vector_t extractVars(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len) {
|
|
Vector_t args = newVec(sizeof(Variable_t), 5);
|
|
int lastLoc = 0;
|
|
for (int i = 0; i < len; i++) {
|
|
if (tokens[i].token == LSBracket) {
|
|
int distance = distanceBetweenTokens(&tokens[i + 1], len - i - 1, LSBracket, RSBracket);
|
|
i += distance + 1;
|
|
}
|
|
if (tokens[i].token == LBracket){
|
|
int distance = distanceBetweenTokens(&tokens[i + 1], len - i - 1, LBracket, RBracket);
|
|
i += distance + 1;
|
|
}
|
|
if (tokens[i].token == Seperator) {
|
|
Variable_t res = solveEquation(ctx, &tokens[lastLoc], i - lastLoc, 0);
|
|
lastLoc = i + 1;
|
|
|
|
vecAddElement(&args, res);
|
|
}
|
|
|
|
if (i + 1 >= len) {
|
|
Variable_t res = solveEquation(ctx, &tokens[lastLoc], i + 1 - lastLoc, 0);
|
|
vecAddElement(&args, res);
|
|
}
|
|
}
|
|
|
|
return args;
|
|
}
|
|
|
|
#define ErrValue(err) (Variable_t) {.varType = ErrType, .integerType = err}
|
|
#define IntValue(i) (Variable_t) {.varType = IntType, .integerType = i}
|
|
#define StrValue(s) (Variable_t) {.varType = StringType, .stringType = s}
|
|
|
|
#define ELIFTX(x) else if (tokens[i].token == x)
|
|
|
|
Variable_t getVarFromToken(scriptCtx_t* ctx, lexarToken_t* tokens, int* index, u32 maxLen) {
|
|
Variable_t val = { 0 };
|
|
int i = *index;
|
|
|
|
if (tokens[i].token == Variable) {
|
|
Variable_t* var = dictVectorFind(&ctx->varDict, tokens[i].text);
|
|
if (var != NULL) {
|
|
val = *var;
|
|
val.free = 0;
|
|
}
|
|
else {
|
|
val = ErrValue(ERRNOVAR);
|
|
}
|
|
}
|
|
ELIFTX(IntLit) {
|
|
val = IntValue(tokens[i].val);
|
|
}
|
|
ELIFTX(StrLit) {
|
|
val = StrValue(tokens[i].text);
|
|
val.free = 0;
|
|
}
|
|
ELIFTX(ArrayVariable) {
|
|
Variable_t* var = dictVectorFind(&ctx->varDict, tokens[i].text);
|
|
i += 2;
|
|
|
|
if (var == NULL)
|
|
return ErrValue(ERRNOVAR);
|
|
|
|
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LSBracket, RSBracket);
|
|
if (argCount < 0)
|
|
return ErrValue(ERRSYNTAX);
|
|
|
|
Variable_t index = solveEquation(ctx, &tokens[i], argCount, 0);
|
|
i += argCount;
|
|
|
|
if (index.varType != IntType)
|
|
return ErrValue(ERRINVALIDTYPE);
|
|
|
|
if (var->vectorType.count <= index.integerType || index.integerType < 0)
|
|
return ErrValue(ERRSYNTAX);
|
|
|
|
switch (var->varType) {
|
|
case StringArrayType:
|
|
val = StrValue((vecGetArray(char**, var->vectorType))[index.integerType]);
|
|
break;
|
|
case IntArrayType:
|
|
val = IntValue((vecGetArray(int*, var->vectorType))[index.integerType]);
|
|
break;
|
|
case ByteArrayType:
|
|
val = IntValue((vecGetArray(u8*, var->vectorType))[index.integerType]);
|
|
break;
|
|
default:
|
|
return ErrValue(ERRINVALIDTYPE);
|
|
}
|
|
}
|
|
ELIFTX(Function) {
|
|
i += 2;
|
|
|
|
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LBracket, RBracket);
|
|
if (argCount < 0)
|
|
return ErrValue(ERRSYNTAX);
|
|
|
|
val = executeFunction(ctx, tokens[i - 2].text, &tokens[i], argCount);
|
|
|
|
i += argCount;
|
|
}
|
|
ELIFTX(LSBracket) {
|
|
i++;
|
|
|
|
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LSBracket, RSBracket);
|
|
if (argCount < 0)
|
|
return ErrValue(ERRSYNTAX);
|
|
|
|
val.varType = EmptyArrayType;
|
|
|
|
if (argCount > 0){
|
|
Vector_t arrayVars = extractVars(ctx, &tokens[i], argCount);
|
|
Variable_t* variables = vecGetArray(Variable_t*, arrayVars);
|
|
int type = variables[0].varType;
|
|
if (!(type == StringType || type == IntType))
|
|
return ErrValue(ERRINVALIDTYPE);
|
|
|
|
val.varType = (type + 2);
|
|
val.free = 1;
|
|
val.vectorType = newVec((type == IntType) ? sizeof(int) : sizeof(char*), arrayVars.count);
|
|
|
|
for (int j = 0; j < arrayVars.count; j++) {
|
|
if (variables[j].varType != type)
|
|
return ErrValue(ERRINVALIDTYPE); // Free-ing issue!!
|
|
|
|
if (type == StringType) {
|
|
char* temp = CpyStr(variables[j].stringType);
|
|
vecAddElement(&val.vectorType, temp);
|
|
}
|
|
else {
|
|
vecAddElement(&val.vectorType, variables[j].integerType);
|
|
}
|
|
}
|
|
|
|
i += argCount;
|
|
freeVariableVector(&arrayVars);
|
|
}
|
|
}
|
|
ELIFTX(LBracket) {
|
|
i++;
|
|
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LBracket, RBracket);
|
|
if (argCount < 0)
|
|
return ErrValue(ERRSYNTAX);
|
|
|
|
val = solveEquation(ctx, &tokens[i], argCount, 0);
|
|
i += argCount;
|
|
}
|
|
else {
|
|
// ERR
|
|
return ErrValue(ERRSYNTAX);
|
|
}
|
|
|
|
*index = i;
|
|
return val;
|
|
}
|
|
|
|
int matchTypes(Variable_t d1, Variable_t d2, int type) {
|
|
return (d1.varType == d2.varType && d1.varType == type);
|
|
}
|
|
|
|
#define ELIFT(token) else if (localOpToken == token)
|
|
|
|
Variable_t solveEquation(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len, u8 shouldFree) {
|
|
Variable_t res = { 0 };
|
|
u8 lastToken = 0;
|
|
u8 invertValue = 0;
|
|
lexarToken_t* varToken = NULL;
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
if (tokens[i].token == Not)
|
|
invertValue = !invertValue;
|
|
|
|
else if (tokens[i].token == ArrayVariableAssignment || tokens[i].token == VariableAssignment) {
|
|
varToken = &tokens[i];
|
|
if (tokens[i].token == ArrayVariableAssignment) {
|
|
int distance = distanceBetweenTokens(&tokens[i] + 2, len, LSBracket, RSBracket);
|
|
i += distance + 2;
|
|
}
|
|
}
|
|
|
|
else if (tokens[i].token >= Variable && tokens[i].token <= LSBracket) {
|
|
Variable_t val = getVarFromToken(ctx, tokens, &i, len - i);
|
|
|
|
if (val.varType == ErrType)
|
|
return val;
|
|
|
|
if (val.varType == IntType && invertValue) {
|
|
val.integerType = !val.integerType;
|
|
}
|
|
invertValue = 0;
|
|
|
|
if (lastToken) {
|
|
u16 localOpToken = lastToken; // do we need local op token?
|
|
lastToken = 0;
|
|
|
|
if (matchTypes(res, val, IntType)) {
|
|
if (localOpToken == Plus)
|
|
res.integerType += val.integerType;
|
|
ELIFT(Minus)
|
|
res.integerType -= val.integerType;
|
|
ELIFT(Multiply)
|
|
res.integerType *= val.integerType;
|
|
ELIFT(Division) {
|
|
if (!val.integerType)
|
|
res = ErrValue(ERRDIVBYZERO);
|
|
else
|
|
res.integerType = res.integerType / val.integerType;
|
|
}
|
|
ELIFT(Mod)
|
|
res.integerType %= val.integerType;
|
|
ELIFT(Smaller)
|
|
res.integerType = res.integerType < val.integerType;
|
|
ELIFT(SmallerEqual)
|
|
res.integerType = res.integerType <= val.integerType;
|
|
ELIFT(Bigger)
|
|
res.integerType = res.integerType > val.integerType;
|
|
ELIFT(BiggerEqual)
|
|
res.integerType = res.integerType >= val.integerType;
|
|
ELIFT(EqualEqual)
|
|
res.integerType = res.integerType == val.integerType;
|
|
ELIFT(NotEqual)
|
|
res.integerType = res.integerType != val.integerType;
|
|
ELIFT(LogicAND) {
|
|
res.integerType = res.integerType && val.integerType;
|
|
if (!res.integerType)
|
|
break;
|
|
}
|
|
ELIFT(LogicOR) {
|
|
res.integerType = res.integerType || val.integerType;
|
|
if (res.integerType)
|
|
break;
|
|
}
|
|
ELIFT(AND)
|
|
res.integerType = res.integerType & val.integerType;
|
|
ELIFT(OR)
|
|
res.integerType = res.integerType | val.integerType;
|
|
ELIFT(BitShiftLeft)
|
|
res.integerType = res.integerType << val.integerType;
|
|
ELIFT(BitShiftRight)
|
|
res.integerType = res.integerType >> val.integerType;
|
|
else
|
|
return ErrValue(ERRBADOPERATOR);
|
|
}
|
|
else if (matchTypes(res, val, StringType)) {
|
|
if (localOpToken == Plus) {
|
|
char* buff = calloc(strlen(res.stringType) + strlen(val.stringType) + 1, 1);
|
|
strcpy(buff, res.stringType);
|
|
strcat(buff, val.stringType);
|
|
|
|
if (res.free) free(res.stringType); // we should replace these with variablefree
|
|
if (val.free) free(val.stringType);
|
|
res.stringType = buff;
|
|
res.free = 1;
|
|
}
|
|
ELIFT(EqualEqual) {
|
|
res.typeUnion = IntType;
|
|
int compRes = !strcmp(res.stringType, val.stringType);
|
|
if (res.free) free(res.stringType);
|
|
if (val.free) free(val.stringType);
|
|
res.integerType = compRes;
|
|
res.free = 0;
|
|
}
|
|
ELIFT(Minus) {
|
|
u32 lenRes = strlen(res.stringType);
|
|
u32 valRes = strlen(val.stringType);
|
|
if (!strcmp(res.stringType + lenRes - valRes, val.stringType)) {
|
|
char *temp = malloc(lenRes - valRes + 1);
|
|
memcpy(temp, res.stringType, lenRes - valRes);
|
|
temp[lenRes - valRes] = 0;
|
|
freeVariable(res);
|
|
res.free = 1;
|
|
res.stringType = temp;
|
|
}
|
|
|
|
freeVariable(val);
|
|
}
|
|
ELIFT(Division) {
|
|
int valLen = strlen(val.stringType);
|
|
if (!valLen) {
|
|
res = ErrValue(ERRSYNTAX);
|
|
continue;
|
|
}
|
|
|
|
char* start = res.stringType;
|
|
char* find = NULL;
|
|
Vector_t arr = newVec(sizeof(char**), 10);
|
|
char* temp;
|
|
|
|
while ((find = (strstr(start, val.stringType))) != NULL) {
|
|
temp = utils_copyStringSize(start, find - start);
|
|
vecAddElement(&arr, temp);
|
|
|
|
start = find + valLen;
|
|
}
|
|
|
|
temp = utils_copyStringSize(start, res.stringType + strlen(res.stringType) - start);
|
|
vecAddElement(&arr, temp);
|
|
if (res.free) free(res.stringType); // do we free here?
|
|
if (val.free) free(val.stringType);
|
|
|
|
res.varType = StringArrayType;
|
|
res.free = 1;
|
|
res.vectorType = arr;
|
|
}
|
|
else
|
|
return ErrValue(ERRBADOPERATOR);
|
|
}
|
|
else if ((res.varType == IntArrayType || res.varType == ByteArrayType) && val.varType == IntType) {
|
|
if (localOpToken == Plus) {
|
|
Vector_t newV = vecCopy(&res.vectorType);
|
|
freeVariable(res);
|
|
res.vectorType = newV;
|
|
res.free = 1;
|
|
if (res.varType == IntArrayType)
|
|
vecAddElement(&res.vectorType, val.integerType);
|
|
else {
|
|
u8 in = ((u8)val.integerType & 0xFF);
|
|
vecAddElement(&res.vectorType, in);
|
|
}
|
|
}
|
|
ELIFT(Minus){
|
|
if (val.integerType >= res.vectorType.count)
|
|
return ErrValue(ERRSYNTAX);
|
|
|
|
res.vectorType.count -= val.integerType;
|
|
Vector_t newV = vecCopy(&res.vectorType);
|
|
freeVariable(res);
|
|
res.vectorType = newV;
|
|
res.free = 1;
|
|
}
|
|
ELIFT(Selector){
|
|
if (val.integerType >= res.vectorType.count)
|
|
return ErrValue(ERRSYNTAX);
|
|
|
|
Vector_t newV = vecCopyOffset(&res.vectorType, val.integerType);
|
|
freeVariable(res);
|
|
res.vectorType = newV;
|
|
res.free = 1;
|
|
}
|
|
}
|
|
else if (res.varType == StringType && val.varType == IntType){
|
|
if (localOpToken == Minus){
|
|
u32 resLen = strlen(res.stringType);
|
|
if (resLen < val.integerType)
|
|
return ErrValue(ERRSYNTAX);
|
|
|
|
char *temp = utils_copyStringSize(res.stringType, resLen - val.integerType);
|
|
|
|
freeVariable(res);
|
|
res.stringType = temp;
|
|
res.free = 1;
|
|
}
|
|
ELIFT(Selector){
|
|
u32 resLen = strlen(res.stringType);
|
|
if (resLen < val.integerType)
|
|
return ErrValue(ERRSYNTAX);
|
|
|
|
char *temp = CpyStr(res.stringType + val.integerType);
|
|
|
|
freeVariable(res);
|
|
res.stringType = temp;
|
|
res.free = 1;
|
|
}
|
|
else
|
|
return ErrValue(ERRBADOPERATOR);
|
|
}
|
|
else if (res.varType == EmptyArrayType && localOpToken == Plus){
|
|
res.free = 1;
|
|
res.varType = val.varType + 2;
|
|
|
|
if (val.varType == IntType){
|
|
res.vectorType = newVec(sizeof(int), 4);
|
|
vecAddElem(&res.vectorType, val.integerType);
|
|
}
|
|
else if (val.varType == StringType) {
|
|
res.vectorType = newVec(sizeof(char*), 4);
|
|
char *temp = CpyStr(val.stringType);
|
|
vecAddElem(&res.vectorType, temp);
|
|
}
|
|
else
|
|
return ErrValue(ERRBADOPERATOR);
|
|
|
|
freeVariable(val);
|
|
}
|
|
else if (res.varType == StringArrayType && val.varType == StringType){
|
|
if (localOpToken == Plus){
|
|
Vector_t new = vecCopy(&res.vectorType);
|
|
vecDefArray(char **, strings, new);
|
|
for (int j = 0; j < new.count; j++){
|
|
strings[j] = CpyStr(strings[j]);
|
|
}
|
|
|
|
freeVariable(res);
|
|
|
|
char *temp = CpyStr(val.stringType);
|
|
vecAddElem(&new, temp);
|
|
|
|
res.free = 1;
|
|
res.vectorType = new;
|
|
}
|
|
else
|
|
return ErrValue(ERRBADOPERATOR);
|
|
}
|
|
else
|
|
return ErrValue(ERRBADOPERATOR);
|
|
}
|
|
else {
|
|
res = val;
|
|
}
|
|
}
|
|
else if (tokens[i].token >= Plus && tokens[i].token <= BitShiftRight) {
|
|
lastToken = tokens[i].token;
|
|
}
|
|
}
|
|
|
|
if (varToken != NULL) {
|
|
if (varToken->token == VariableAssignment) {
|
|
dict_t newVar = newDict(CpyStr(varToken->text), res);
|
|
dictVectorAdd(&ctx->varDict, newVar);
|
|
}
|
|
else {
|
|
Variable_t* var = dictVectorFind(&ctx->varDict, varToken->text);
|
|
if (var != NULL) {
|
|
if (var->varType - 2 == res.varType || (var->varType == ByteArrayType && res.varType == IntType)) {
|
|
int distance = distanceBetweenTokens(varToken + 2, len, LSBracket, RSBracket);
|
|
if (distance < 0) {
|
|
// ERR
|
|
return ErrValue(ERRSYNTAX);
|
|
}
|
|
Variable_t index = solveEquation(ctx, varToken + 2, distance, 0);
|
|
if (index.varType != IntType) {
|
|
// ERR
|
|
}
|
|
else if (index.integerType < 0 || var->vectorType.count <= index.integerType) {
|
|
// ERR
|
|
}
|
|
else {
|
|
if (var->varType == IntArrayType) {
|
|
int* arr = vecGetArray(int*, var->vectorType);
|
|
arr[index.integerType] = res.integerType;
|
|
}
|
|
else if (var->varType == StringArrayType) {
|
|
char** arr = vecGetArray(char**, var->vectorType);
|
|
arr[index.integerType] = CpyStr(res.stringType);
|
|
}
|
|
else if (var->varType == ByteArrayType) {
|
|
u8* arr = vecGetArray(u8*, var->vectorType);
|
|
arr[index.integerType] = res.integerType & 0xFF;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// ERR
|
|
}
|
|
}
|
|
else {
|
|
//ERR
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (shouldFree) // we should get rid of this ugly free. why not set .free to 0 when assigning it then free in parser.c?
|
|
freeVariable(res);
|
|
}
|
|
|
|
return res;
|
|
} |