start of tsV2

This commit is contained in:
suchmememanyskill 2020-11-06 21:19:29 +01:00
parent 024ef7cd6e
commit ba0ded0f8b
21 changed files with 1235 additions and 1205 deletions

View File

@ -540,6 +540,11 @@ void gfx_boxGrey(int x0, int y0, int x1, int y1, u8 shade){
memset(gfx_ctxt.fb + y * gfx_ctxt.stride + y0, shade, (y1 - y0 + 1) * 4);
}
}
void gfx_setPixel(int x, int y, u32 color) {
*(gfx_ctxt.fb + (YLEFT - x) * gfx_ctxt.stride + y) = color;
}
/*
void gfx_boxGrey_old(int x0, int y0, int x1, int y1, u8 shade){
for (int y = y0; y <= y1; y++){

View File

@ -53,6 +53,7 @@ void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 po
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
void gfx_box(int x0, int y0, int x1, int y1, u32 color);
void gfx_boxGrey(int x0, int y0, int x1, int y1, u8 shade);
void gfx_setPixel(int x, int y, u32 color);
/*
#define GFX_SETPOSCORRECTED(x, y) gfx_con_setpos(y - YLEFT, x)

View File

@ -58,4 +58,6 @@ typedef struct {
} gpt_entry_rule;
#define isFS 0x80
#define isBOOT 0x2
#define isBOOT 0x2
typedef void (*func_void_ptr)();

View File

@ -204,7 +204,7 @@ int filemenu(menu_entry file){
while (hidRead()->buttons);
*/
runScript(fsutil_getnextloc(currentpath, file.name));
startScript(fsutil_getnextloc(currentpath, file.name));
fsreader_readfolder(currentpath);
break;
case FILE_HEXVIEW:

View File

@ -0,0 +1,281 @@
#include "args.h"
#include "parser.h"
#include "scriptCtx.h"
#include "lexer.h"
#include "functions.h"
#include "list.h"
#include <string.h>
#include "../../mem/heap.h"
#include "../utils/utils.h"
// 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;
}
dictValue_t getVarFromToken(scriptCtx_t* ctx, lexarToken_t* tokens, int* index, u32 maxLen) {
dictValue_t val = { 0 };
val.free = 0;
int i = *index;
u8 not = 0;
if (tokens[i].token == Not) {
not = 1;
i++;
}
if (tokens[i].token == Not)
return ErrDictValue(ERRDOUBLENOT);
if (tokens[i].token == Variable) {
char* funcName = tokens[i].text;
if (tokens[i + 1].token == LBracket) {
i += 2;
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LBracket, RBracket);
if (argCount < 0)
return ErrDictValue(ERRSYNTAX);
ctx->args_loc.tokens = &tokens[i];
ctx->args_loc.stored = argCount;
val = executeFunction(ctx, funcName);
i += argCount;
}
else if (tokens[i + 1].token == LSBracket) {
dictValue_t* var = varVectorFind(&ctx->vars, tokens[i].text);
i += 2;
if (var == NULL)
return ErrDictValue(ERRNOVAR);
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LSBracket, RSBracket);
if (argCount < 0)
return ErrDictValue(ERRSYNTAX);
dictValue_t index = solveEquation(ctx, &tokens[i], argCount);
i += argCount;
if (index.varType != IntType)
return ErrDictValue(ERRINVALIDTYPE);
if (var->arrayLen <= index.integer || index.integer < 0)
return ErrDictValue(ERRSYNTAX);
switch (var->varType) {
case StringArrayType:
val = StrDictValue(var->stringArray[index.integer]);
break;
case IntArrayType:
val = IntDictValue(var->integerArray[index.integer]);
break;
case ByteArrayType:
val = IntDictValue(var->byteArray[index.integer]);
break;
default:
return ErrDictValue(ERRINVALIDTYPE);
}
}
else {
dictValue_t* var = varVectorFind(&ctx->vars, tokens[i].text);
if (var != NULL) {
if (var->type == IntType) {
val = IntDictValue(var->integer);
}
else if (var->type == StringType){
val = StrDictValue(util_cpyStr(var->string));
val.free = 1;
}
else {
val = *var;
val.free = 0;
}
}
else
return ErrDictValue(ERRNOVAR);
}
}
else if (tokens[i].token == LSBracket) {
i++;
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LSBracket, RSBracket);
if (argCount <= 0)
return ErrDictValue(-5);
varVector_t arrayVars = extractVars(ctx, &tokens[i], argCount);
int type = arrayVars.vars[0].value.varType;
if (!(type == StringType || type == IntType))
return ErrDictValue(ERRINVALIDTYPE);
val.type = (type + 2) | FREEINDICT;
val.arrayLen = arrayVars.stored;
val.integerArray = calloc(val.arrayLen, (type == IntType) ? sizeof(int) : sizeof(char*));
val.free = (type == StringType) ? 1 : 0;
for (int i = 0; i < arrayVars.stored; i++) {
if (arrayVars.vars[i].value.varType != type)
return ErrDictValue(ERRINVALIDTYPE); // Free-ing issue!!
if (type == StringType) {
val.stringArray[i] = util_cpyStr(arrayVars.vars[i].value.string);
}
else {
val.integerArray[i] = arrayVars.vars[i].value.integer;
}
}
i += argCount;
varVectorFree(&arrayVars);
}
else if (tokens[i].token == LBracket) {
i += 1;
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LBracket, RBracket);
if (argCount < 0)
return ErrDictValue(ERRSYNTAX);
val = solveEquation(ctx, &tokens[i], argCount);
i += argCount;
}
else if (tokens[i].token == IntLit) {
val = IntDictValue(tokens[i].val);
}
else if (tokens[i].token == StrLit) {
val = StrDictValue(tokens[i].text); // Do we need to copy the string here? if we set var.free = 0, it shouldn't matter
val.free = 0;
}
else {
// ERR
return ErrDictValue(ERRNOVAR);
}
if (not) {
if (val.type == IntType)
val.integer = !val.integer;
else
return ErrDictValue(ERRINVALIDTYPE);
}
*index = i;
return val;
}
int matchTypes(dictValue_t d1, dictValue_t d2, int type) {
return (d1.varType == d2.varType && d1.varType == type);
}
#define ELIFT(token) else if (localOpToken == token)
dictValue_t solveEquation(scriptCtx_t *ctx, lexarToken_t* tokens, u32 len) {
dictValue_t res = { 0 };
u16 lastToken = 0;
for (int i = 0; i < len; i++) {
if (tokens[i].token == Variable || tokens[i].token == StrLit || tokens[i].token == IntLit || tokens[i].token == Not || tokens[i].token == LBracket || tokens[i].token == LSBracket){
dictValue_t val = getVarFromToken(ctx, tokens, &i, len - i);
if (val.type == ErrType)
return val;
if (lastToken) {
u16 localOpToken = lastToken; // do we need local op token?
lastToken = 0;
if (matchTypes(res, val, IntType)) {
if (localOpToken == Plus)
res.integer += val.integer;
ELIFT(Minus)
res.integer -= val.integer;
ELIFT(Multiply)
res.integer *= val.integer;
ELIFT(Division)
res.integer /= val.integer;
ELIFT(Mod)
res.integer %= val.integer;
ELIFT(Smaller)
res.integer = res.integer < val.integer;
ELIFT(SmallerEqual)
res.integer = res.integer <= val.integer;
ELIFT(Bigger)
res.integer = res.integer > val.integer;
ELIFT(BiggerEqual)
res.integer = res.integer >= val.integer;
ELIFT(EqualEqual)
res.integer = res.integer == val.integer;
ELIFT(NotEqual)
res.integer = res.integer != val.integer;
ELIFT(LogicAND) {
res.integer = res.integer && val.integer;
if (!res.integer)
break;
}
ELIFT(LogicOR) {
res.integer = res.integer || val.integer;
if (res.integer)
break;
}
ELIFT(AND)
res.integer = res.integer & val.integer;
ELIFT(OR)
res.integer = res.integer | val.integer;
else
return ErrDictValue(ERRBADOPERATOR);
}
else if (matchTypes(res, val, StringType)) {
if (localOpToken == Plus) {
char* buff = calloc(strlen(res.string) + strlen(val.string) + 1, 1);
strcpy(buff, res.string);
strcat(buff, val.string);
if (res.free)
free(res.string);
if (val.free)
free(val.string);
res.string = buff;
}
ELIFT(EqualEqual) {
res.type = IntType;
int compRes = !strcmp(res.string, val.string);
if (res.free)
free(res.string);
if (val.free)
free(val.string);
res.integer = compRes;
res.free = 0;
}
ELIFT(Minus) {
if (!strcmp(res.string + strlen(res.string) - strlen(val.string), val.string)) {
*(res.string + strlen(res.string) - strlen(val.string)) = 0;
}
free(val.string);
}
else
return ErrDictValue(ERRBADOPERATOR);
}
else
return ErrDictValue(ERRBADOPERATOR);
}
else {
res = val;
}
}
else if (tokens[i].token >= Plus && tokens[i].token <= OR) {
lastToken = tokens[i].token;
}
}
return res;
}

View File

@ -0,0 +1,6 @@
#pragma once
#include "types.h"
char* createStrOutTextHolder(textHolder_t t);
dictValue_t solveEquation(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len);
int distanceBetweenTokens(lexarToken_t* tokens, u32 len, int openToken, int closeToken);

View File

@ -1,664 +1,177 @@
#include <string.h>
#include <stdlib.h>
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../emmc/emmc.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../utils/sprintf.h"
#include "../../hid/hid.h"
#include "../../gfx/gfx.h"
#include "../../utils/util.h"
#include "../../storage/emummc.h"
#include "parser.h"
#include "../common/common.h"
#include "../fs/fsactions.h"
#include "variables.h"
#include "../utils/utils.h"
#include "functions.h"
#include "../fs/fsutils.h"
#include "../../utils/sprintf.h"
#include "../fs/fsactions.h"
#include "../emmc/emmcoperations.h"
#include "../emmc/emmcmenu.h"
#include "list.h"
#include "args.h"
#include "parser.h"
#include "lexer.h"
#include "types.h"
#include "scriptCtx.h"
#include "../../gfx/gfx.h"
#include "../../mem/heap.h"
#include <string.h>
#include "../../hid/hid.h"
extern FIL scriptin;
extern char **argv;
extern u32 argc;
extern int forceExit;
extern short currentlyMounted;
dictValue_t funcPrint(scriptCtx_t* ctx, varVector_t* args) {
for (int i = 0; i < args->stored; i++) {
switch (args->vars[i].value.varType) {
case IntType:
gfx_printf("%d", args->vars[i].value.integer);
break;
case StringType:
gfx_printf("%s", args->vars[i].value.string);
break;
}
}
int parseIntInput(char *in, int *out){
if (in[0] == '@'){
if (str_int_find(in, out))
return -1;
}
else
*out = atoi(in);
return 0;
}
/*
int parseJmpInput(char *in, u64 *out){
if (in[0] == '?'){
if (str_jmp_find(in, out))
return -1;
else
return 0;
}
else
return -1;
}
*/
int parseStringInput(char *in, char **out){
if (in[0] == '$'){
if (str_str_find(in, out))
return -1;
else
return 0;
}
else{
*out = in;
return 0;
}
return NullDictValue();
}
#pragma GCC push_options
#pragma GCC optimize ("Os")
u32 currentcolor = COLOR_WHITE;
int part_printf(){
SWAPCOLOR(currentcolor);
for (int i = 0; i < argc; i++){
if (argv[i][0] == '@'){
int toprintint;
if (parseIntInput(argv[i], &toprintint))
return INFUNC_FAIL;
gfx_printf("%d", toprintint);
}
else {
char *toprintstring;
if (parseStringInput(argv[i], &toprintstring))
return INFUNC_FAIL;
gfx_printf(toprintstring);
}
}
gfx_printf("\n");
return 0;
dictValue_t funcPrintln(scriptCtx_t* ctx, varVector_t* args) {
funcPrint(ctx, args);
gfx_printf("\n");
return NullDictValue();
}
int part_print_int(){
int toprint;
if (parseIntInput(argv[0], &toprint))
return INFUNC_FAIL;
SWAPCOLOR(currentcolor);
gfx_printf("%s: %d\n", argv[0], toprint);
return 0;
dictValue_t funcIf(scriptCtx_t* ctx, varVector_t* args) {
if (args->vars[0].value.varType == IntType) {
setCurIndentInstruction(ctx, (args->vars[0].value.integer == 0), -1);
return NullDictValue();
}
return ErrDictValue(ERRINVALIDTYPE);
}
int part_Wait(){
int arg;
u32 begintime;
SWAPCOLOR(currentcolor);
if (parseIntInput(argv[0], &arg))
return INFUNC_FAIL;
begintime = get_tmr_s();
while (begintime + arg > get_tmr_s()){
gfx_printf("\r<Wait %d seconds> ", (begintime + arg) - get_tmr_s());
}
gfx_printf("\r \r");
return 0;
dictValue_t scriptElse(scriptCtx_t* ctx, varVector_t* args) {
indentInstructor_t curInstruction = getCurIndentInstruction(ctx);
setCurIndentInstruction(ctx, !curInstruction.skip, -1);
return NullDictValue();
}
int part_Check(){
int left, right;
if (parseIntInput(argv[0], &left))
return INFUNC_FAIL;
if (parseIntInput(argv[2], &right))
return INFUNC_FAIL;
dictValue_t scriptWhile(scriptCtx_t* ctx, varVector_t* args) {
if (args->vars[0].value.varType == IntType) {
setCurIndentInstruction(ctx, (args->vars[0].value.integer == 0), ctx->lastTokenPos);
return NullDictValue();
}
if (!strcmp(argv[1], "=="))
return (left == right);
else if (!strcmp(argv[1], "!="))
return (left != right);
else if (!strcmp(argv[1], ">="))
return (left >= right);
else if (!strcmp(argv[1], "<="))
return (left <= right);
else if (!strcmp(argv[1], ">"))
return (left > right);
else if (!strcmp(argv[1], "<"))
return (left < right);
else
return INFUNC_FAIL;
return ErrDictValue(ERRINVALIDTYPE);
}
int part_if(){
int condition;
if (parseIntInput(argv[0], &condition))
return INFUNC_FAIL;
dictValue_t scriptLen(scriptCtx_t* ctx, varVector_t* args) {
if (args->vars[0].value.varType >= IntArrayType && args->vars[0].value.varType <= ByteArrayType)
return IntDictValue(args->vars[0].value.arrayLen);
else if (args->vars[0].value.varType == StringType) {
if (args->vars[0].value.string != NULL)
return IntDictValue(strlen(args->vars[0].value.string));
}
getfollowingchar('{');
if (!condition)
skipbrackets();
return 0;
/*
if (condition)
return 0;
else {
skipbrackets();
return 0;
}
*/
return ErrDictValue(ERRINVALIDTYPE);
}
int part_if_args(){
int condition;
if ((condition = part_Check()) < 0)
return INFUNC_FAIL;
dictValue_t scriptMakeByteArray(scriptCtx_t* ctx, varVector_t* args) {
if (args->vars[0].value.varType == IntArrayType) {
u8* buff = calloc(args->vars[0].value.arrayLen, 1);
for (int i = 0; i < args->vars[0].value.arrayLen; i++) {
buff[i] = (u8)(args->vars[0].value.integerArray[i] & 0xFF);
}
getfollowingchar('{');
return DictValueCreate(ByteArrayType | FREEINDICT, args->vars[0].value.arrayLen, buff);
}
if (!condition)
skipbrackets();
return 0;
return ErrDictValue(ERRINVALIDTYPE);
}
int part_Math(){
int left, right;
if (parseIntInput(argv[0], &left))
return INFUNC_FAIL;
if (parseIntInput(argv[2], &right))
return INFUNC_FAIL;
switch (argv[1][0]){
case '+':
return left + right;
case '-':
return left - right;
case '*':
return left * right;
case '/':
return left / right;
}
return INFUNC_FAIL;
dictValue_t scriptWait(scriptCtx_t*ctx, varVector_t* args){
Inputs* input = hidWait();
return IntDictValue(input->buttons);
}
int part_SetInt(){
int out;
parseIntInput(argv[0], &out);
return out;
dictValue_t scriptSetPixel(scriptCtx_t *ctx, varVector_t* args){
int pixelArgs[5] = {0};
for (int i = 0; i < args->stored; i++){
if (args->vars[i].value.varType != IntType)
return ErrDictValue(ERRINVALIDTYPE);
pixelArgs[i] = args->vars[i].value.integer;
}
u32 color = 0xFF000000 | ((pixelArgs[2] & 0xFF) << 16) | ((pixelArgs[3] & 0xFF) << 8) | ((pixelArgs[4] & 0xFF));
gfx_setPixel(pixelArgs[0], pixelArgs[1], color);
return NullDictValue();
}
int part_SetString(){
char *arg0;
if (parseStringInput(argv[0], &arg0))
return INFUNC_FAIL;
if (argv[1][0] != '$')
return INFUNC_FAIL;
str_str_add(argv[1], arg0);
return 0;
}
int part_SetStringIndex(){
int index;
char *out;
if (parseIntInput(argv[0], &index))
return INFUNC_FAIL;
if (argv[1][0] != '$')
return INFUNC_FAIL;
if (str_str_index(index, &out))
return INFUNC_FAIL;
str_str_add(argv[1], out);
return 0;
}
int part_goto(){
int target = 0;
if (parseIntInput(argv[0], &target))
return INFUNC_FAIL;
str_int_add("@RETURN", (int)f_tell(&scriptin));
f_lseek(&scriptin, target);
return 0;
}
int part_invert(){
int arg;
if (parseIntInput(argv[0], &arg))
return INFUNC_FAIL;
return (arg) ? 0 : 1;
}
int part_fs_exists(){
char *path;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
return fsutil_checkfile(path);
}
int part_ConnectMMC(){
char *arg;
parseStringInput(argv[0], &arg);
if (!strcmp(arg, "SYSMMC"))
connect_mmc(SYSMMC);
else if (!strcmp(arg, "EMUMMC"))
connect_mmc(EMUMMC);
else
return INFUNC_FAIL;
return 0;
}
int part_MountMMC(){
char *arg;
parseStringInput(argv[0], &arg);
return mount_mmc(arg, 2);
}
int part_Pause(){
Inputs *input = hidWaitMask(KEY_A | KEY_B | KEY_X | KEY_Y | KEY_POW | KEY_VOLP | KEY_VOLM | KEY_LUP | KEY_LDOWN | KEY_LLEFT | KEY_LRIGHT);
str_int_add("@BTN_POWER", input->pow);
str_int_add("@BTN_VOL+", input->volp);
str_int_add("@BTN_VOL-", input->volm);
str_int_add("@BTN_A", input->a);
str_int_add("@BTN_B", input->b);
str_int_add("@BTN_X", input->x);
str_int_add("@BTN_Y", input->y);
str_int_add("@BTN_UP", input->Lup);
str_int_add("@BTN_DOWN", input->Ldown);
str_int_add("@BTN_LEFT", input->Lleft);
str_int_add("@BTN_RIGHT", input->Lright);
str_int_add("@JOYCONN", hidConnected());
return input->buttons;
}
int part_addstrings(){
char *combined, *left, *middle;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &middle))
return INFUNC_FAIL;
if (argv[2][0] != '$')
return INFUNC_FAIL;
combined = calloc(strlen(left) + strlen(middle) + 1, sizeof(char));
sprintf(combined, "%s%s", left, middle);
str_str_add(argv[2], combined);
free(combined);
return 0;
}
int part_setColor(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
if (!strcmp(arg, "RED"))
currentcolor = COLOR_RED;
else if (!strcmp(arg, "ORANGE"))
currentcolor = COLOR_ORANGE;
else if (!strcmp(arg, "YELLOW"))
currentcolor = COLOR_YELLOW;
else if (!strcmp(arg, "GREEN"))
currentcolor = COLOR_GREEN;
else if (!strcmp(arg, "BLUE"))
currentcolor = COLOR_BLUE;
else if (!strcmp(arg, "VIOLET"))
currentcolor = COLOR_VIOLET;
else if (!strcmp(arg, "WHITE"))
currentcolor = COLOR_WHITE;
else
return INFUNC_FAIL;
return 0;
}
int part_Exit(){
forceExit = true;
return 0;
}
int part_fs_Move(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
int res;
res = f_rename(left, right);
if (res)
res = f_rename(left, right);
return res;
}
int part_fs_Delete(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
int res;
res = f_unlink(arg);
if (res)
res = f_unlink(arg);
return res;
}
int part_fs_DeleteRecursive(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
return fsact_del_recursive(arg);
}
int part_fs_Copy(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
return fsact_copy(left, right, COPY_MODE_PRINT);
}
int part_fs_CopyRecursive(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
return fsact_copy_recursive(left, right);
}
int part_fs_MakeDir(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
int res;
res = f_mkdir(arg);
if (res)
res = f_mkdir(arg);
return res;
}
DIR dir;
FILINFO fno;
int isdirvalid = false;
int part_fs_OpenDir(){
char *path;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
if (f_opendir(&dir, path))
return INFUNC_FAIL;
isdirvalid = true;
str_int_add("@ISDIRVALID", isdirvalid);
return 0;
}
int part_fs_CloseDir(){
if (!isdirvalid)
return 0;
f_closedir(&dir);
isdirvalid = false;
str_int_add("@ISDIRVALID", isdirvalid);
return 0;
}
int part_fs_ReadDir(){
if (!isdirvalid)
return INFUNC_FAIL;
if (!f_readdir(&dir, &fno) && fno.fname[0]){
str_str_add("$FILENAME", fno.fname);
str_int_add("@ISDIR", (fno.fattrib & AM_DIR) ? 1 : 0);
}
else {
part_fs_CloseDir();
}
return 0;
}
int part_setPrintPos(){
int left, right;
if (parseIntInput(argv[0], &left))
return INFUNC_FAIL;
if (parseIntInput(argv[1], &right))
return INFUNC_FAIL;
if (left > 78)
return INFUNC_FAIL;
if (right > 42)
return INFUNC_FAIL;
gfx_con_setpos(left * 16, right * 16);
return 0;
}
int part_stringcompare(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
return (strcmp(left, right)) ? 0 : 1;
}
int part_fs_combinePath(){
char *combined, *left, *middle;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &middle))
return INFUNC_FAIL;
if (argv[2][0] != '$')
return INFUNC_FAIL;
combined = fsutil_getnextloc(left, middle);
str_str_add(argv[2], combined);
free(combined);
return 0;
}
int part_mmc_dumpPart(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
if (!strcmp(left, "BOOT")){
return emmcDumpBoot(right);
}
else {
return emmcDumpSpecific(left, right);
}
}
int part_mmc_restorePart(){
char *path;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
if (currentlyMounted < 0)
return INFUNC_FAIL;
return mmcFlashFile(path, currentlyMounted, false);
}
int part_fs_extractBisFile(){
char *path, *outfolder;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &outfolder))
return INFUNC_FAIL;
return extract_bis_file(path, outfolder);
}
int part_clearscreen(){
gfx_clearscreen();
return 0;
}
int part_getPos(){
return (int)f_tell(&scriptin);
}
int part_subString(){
char *str, *sub;
int start, size;
if (parseStringInput(argv[0], &str))
return INFUNC_FAIL;
if (parseIntInput(argv[1], &start))
return INFUNC_FAIL;
if (parseIntInput(argv[2], &size))
return INFUNC_FAIL;
if (argv[3][0] != '$')
return INFUNC_FAIL;
if (start >= strlen(str))
return INFUNC_FAIL;
sub = utils_copyStringSize(str + start, size);
str_str_add(argv[3], sub);
free(sub);
return 0;
}
int part_inputString(){
char *start, *out;
int len;
if (parseStringInput(argv[0], &start))
return INFUNC_FAIL;
if (parseIntInput(argv[1], &len))
return INFUNC_FAIL;
if (argv[2][0] != '$')
return INFUNC_FAIL;
if (len > 39)
return INFUNC_FAIL;
out = utils_InputText(start, len);
if (out == NULL)
return 1;
str_str_add(argv[2], out);
free(out);
return 0;
}
int part_strLen(){
char *in;
if (parseStringInput(argv[0], &in))
return INFUNC_FAIL;
return strlen(in);
}
str_fnc_struct functions[] = {
{"printf", part_printf, 255},
{"printInt", part_print_int, 1},
{"setPrintPos", part_setPrintPos, 2},
{"clearscreen", part_clearscreen, 0},
{"if", part_if, 1},
{"if", part_if_args, 3}, // function overloading
{"math", part_Math, 3},
{"check", part_Check, 3},
{"setInt", part_SetInt, 1},
{"goto", part_goto, 1},
{"setString", part_SetString, 2},
{"setStringIndex", part_SetStringIndex, 2},
{"setColor", part_setColor, 1},
{"combineStrings", part_addstrings, 3},
{"compareStrings", part_stringcompare, 2},
{"subString", part_subString, 4},
{"inputString", part_inputString, 3},
{"stringLength", part_strLen, 1},
{"invert", part_invert, 1},
{"fs_exists", part_fs_exists, 1},
{"fs_move", part_fs_Move, 2},
{"fs_mkdir", part_fs_MakeDir, 1},
{"fs_del", part_fs_Delete, 1},
{"fs_delRecursive", part_fs_DeleteRecursive, 1},
{"fs_copy", part_fs_Copy, 2},
{"fs_copyRecursive", part_fs_CopyRecursive, 2},
{"fs_openDir", part_fs_OpenDir, 1},
{"fs_closeDir", part_fs_CloseDir, 0},
{"fs_readDir", part_fs_ReadDir, 0},
{"fs_combinePath", part_fs_combinePath, 3},
{"fs_extractBisFile", part_fs_extractBisFile, 2},
{"mmc_connect", part_ConnectMMC, 1},
{"mmc_mount", part_MountMMC, 1},
{"mmc_dumpPart", part_mmc_dumpPart, 2},
{"mmc_restorePart", part_mmc_restorePart, 1},
{"getPosition", part_getPos, 0},
{"pause", part_Pause, 0},
{"wait", part_Wait, 1},
{"exit", part_Exit, 0},
{NULL, NULL, 0}
const static str_fnc_struct functions[] = {
{"print", funcPrint, {0x40}},
{"println", funcPrintln, {0x40}},
{"if", funcIf, {1}},
{"while", scriptWhile, {1}},
{"else", scriptElse, {0}},
{"len", scriptLen, {1}},
{"byte", scriptMakeByteArray, {1}},
{"wait", scriptWait, {0}},
{"setPixel", scriptSetPixel, {5}},
{NULL, NULL, {0}},
};
#pragma GCC pop_options
varVector_t extractVars(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len) {
varVector_t args = varVectorInit(4);
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 == Seperator) {
dictValue_t res = solveEquation(ctx, &tokens[lastLoc], i - lastLoc);
lastLoc = i + 1;
varVectorAdd(&args, DictCreate(NULL, res));
}
int run_function(char *func_name, int *out){
for (u32 i = 0; functions[i].key != NULL; i++){
if (!strcmp(functions[i].key, func_name)){
if (argc != functions[i].arg_count && functions[i].arg_count != 255)
continue;
if (i + 1 >= len) {
dictValue_t res = solveEquation(ctx, &tokens[lastLoc], i + 1 - lastLoc);
varVectorAdd(&args, DictCreate(NULL, res));
}
}
*out = functions[i].value();
return (*out == INFUNC_FAIL) ? -1 : 0;
}
}
return -2;
return args;
}
dictValue_t executeFunction(scriptCtx_t* ctx, char* func_name) {
int argCount = 0;
varVector_t args = { 0 };
if (ctx->args_loc.stored > 0) {
args = extractVars(ctx, ctx->args_loc.tokens, ctx->args_loc.stored);
for (int i = 0; i < args.stored; i++) {
if (args.vars[i].value.varType == ErrType)
return args.vars[i].value;
}
argCount = args.stored;
}
for (u32 i = 0; functions[i].key != NULL; i++) {
if (!strcmp(functions[i].key, func_name)) {
if (argCount != functions[i].argCount && !functions[i].varArgs)
continue;
dictValue_t val = functions[i].value(ctx, &args);
// free args
varVectorFree(&args);
return val;
}
}
dictValue_t* var = varVectorFind(&ctx->vars, func_name);
if (var != NULL) {
if (var->type == JumpType) {
setCurIndentInstruction(ctx, 0, ctx->curPos);
ctx->curPos = var->integer - 1;
ctx->lastToken.token = Invalid;
return NullDictValue();
}
}
return ErrDictValue(ERRNOFUNC);
}

View File

@ -1,13 +1,10 @@
#pragma once
#include "../../utils/types.h"
#include "types.h"
typedef void (*func_void_ptr)();
typedef int (*func_int_ptr)();
#define BIT(n) (1U << n)
typedef struct {
char *key;
func_int_ptr value;
u8 arg_count;
} str_fnc_struct;
#define VARARGS(x) {x, 1, 0}
#define OPERATORARGS(x) {x, 0, 1}
int run_function(char *func_name, int *out);
dictValue_t executeFunction(scriptCtx_t* ctx, char* func_name);
varVector_t extractVars(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len);

View File

@ -0,0 +1,195 @@
#include "lexer.h"
#include "parser.h"
#include "args.h"
#include "../utils/utils.h"
#include "../../mem/heap.h"
#include <string.h>
static inline int isValidWord(char c) {
char r = c | 0x20;
return (r >= 'a' && r <= 'z');
}
static inline int isValidVar(char c) {
char r = c | 0x20;
return ((r >= 'a' && r <= 'z') || (r >= '0' && r <= '9'));
}
static inline int isValidNum(char c) {
return (c >= '0' && c <= '9');
}
static inline int isValidHexNum(char c) {
char r = c | 0x20;
return (isValidNum(r) || (r >= 'a' && r <= 'f'));
}
#define makeLexarToken(token, var) (lexarToken_t) {token, {var}}
#define makeLexarIntToken(intVar) (lexarToken_t) {IntLit, .val = intVar}
typedef struct {
u8 tokenC;
u16 tokenN;
} lexarTranslation_t;
lexarTranslation_t lexarTranslations[] = {
{'(', LBracket},
{')', RBracket},
{'{', LCBracket},
{'}', RCBracket},
{',', Seperator},
{'+', Plus},
{'-', Minus},
{'*', Multiply},
{'/', Division},
{'%', Mod},
{'<', Smaller},
{'>', Bigger},
{'=', Equal},
{'!', Not},
{'[', LSBracket},
{']', RSBracket},
{'\0', 0},
};
char lexarDebugGetTokenC(u16 tokenN) {
for (int i = 0; lexarTranslations[i].tokenC; i++) {
if (lexarTranslations[i].tokenN == tokenN) {
return lexarTranslations[i].tokenC;
}
}
return '?';
}
lexarVector_t lexarVectorInit(int startSize) {
lexarVector_t l = { 0 };
l.tokens = calloc(startSize, sizeof(lexarVector_t));
l.len = startSize;
l.stored = 0;
return l;
}
void lexarVectorAdd(lexarVector_t* vec, lexarToken_t token) {
if (vec->stored >= vec->len) {
vec->len *= 2;
//vec->tokens = realloc(vec->tokens, vec->len * sizeof(lexarToken_t));
void *temp = calloc(vec->len, sizeof(lexarToken_t));
memcpy(temp, vec->tokens, vec->len / 2 * sizeof(lexarToken_t));
free(vec->tokens);
vec->tokens = temp;
}
vec->tokens[vec->stored++] = token;
}
void lexarVectorClear(lexarVector_t* vec) {
for (int i = 0; i < vec->stored; i++) {
if (vec->tokens[i].token == Variable || vec->tokens[i].token == StrLit)
if (vec->tokens[i].text != NULL)
free(vec->tokens[i].text);
}
free(vec->tokens);
}
#define ELIFC(c) else if (*in == c)
lexarVector_t lexarGo(const char* in) {
lexarVector_t vec = lexarVectorInit(16);
while (*in) {
if (isValidWord(*in)) {
char* startWord = in;
in++;
while (isValidVar(*in))
in++;
lexarVectorAdd(&vec, makeLexarToken(Variable, utils_copyStringSize(startWord, in - startWord)));
continue;
}
else if (isValidNum(*in) || (*in == '-' && isValidNum(in[1]))) {
int parse = 0;
u8 negative = (*in == '-');
if (negative)
in++;
if (*in == '0' && (in[1] | 0x20) == 'x') {
in += 2;
while (isValidHexNum(*in)) {
parse = parse * 16 + (*in & 0x0F) + (*in >= 'A' ? 9 : 0);
in++;
}
}
else while (isValidNum(*in)) {
parse = parse * 10 + *in++ - '0';
}
if (negative)
parse *= -1;
lexarVectorAdd(&vec, makeLexarIntToken(parse));
continue;
}
ELIFC('"') {
char* startStr = ++in;
while (*in != '"')
in++;
lexarVectorAdd(&vec, makeLexarToken(StrLit, utils_copyStringSize(startStr, in - startStr)));
in++;
continue;
}
ELIFC('#') {
while (*in != '\n')
in++;
in++;
continue;
}
ELIFC('&') {
if (in[1] == '&') {
lexarVectorAdd(&vec, makeLexarToken(LogicAND, 0));
in++;
}
else {
lexarVectorAdd(&vec, makeLexarToken(AND, 0));
}
in++;
continue;
}
ELIFC('|') {
if (in[1] == '|') {
lexarVectorAdd(&vec, makeLexarToken(LogicOR, 0));
in++;
}
else {
lexarVectorAdd(&vec, makeLexarToken(OR, 0));
}
in++;
continue;
}
int val = 0;
for (int i = 0; lexarTranslations[i].tokenC; i++) {
if (lexarTranslations[i].tokenC == *in) {
val = lexarTranslations[i].tokenN;
break;
}
}
in++;
if (*in == '=' && val >= Smaller && val <= Not) {
val++;
in++;
}
if (val != Invalid)
lexarVectorAdd(&vec, makeLexarToken(val, 0));
}
return vec;
}

View File

@ -0,0 +1,6 @@
#pragma once
#include "types.h"
lexarVector_t lexarGo(const char* in);
char lexarDebugGetTokenC(u16 tokenN);
void lexarVectorClear(lexarVector_t* vec);

View File

@ -0,0 +1,88 @@
#include "list.h"
#include <string.h>
#include "types.h"
#include "../../mem/heap.h"
void freeDictValue(dictValue_t dv) {
if (dv.string == NULL)
return;
switch (dv.varType) {
case StringType:
case IntArrayType:
case ByteArrayType: // As it's a union with the biggest object being a pointer, this should be the same
free(dv.string);
break;
case StringArrayType:
for (unsigned int i = 0; i < dv.arrayLen; i++)
free(dv.stringArray[i]);
free(dv.stringArray);
}
}
void freeDict(dict_t* dict) {
freeDictValue(dict->value);
free(dict->key);
free(dict);
}
varVector_t varVectorInit(int startSize) {
varVector_t vec = { 0 };
vec.vars = calloc(startSize, sizeof(dict_t));
vec.len = startSize;
vec.stored = 0;
return vec;
}
dictValue_t* varVectorFind(varVector_t* vec, const char* key) {
for (int i = 0; i < vec->stored; i++) {
if (!strcmp(vec->vars[i].key, key))
return &vec->vars[i].value;
}
return NULL;
}
void varVectorAdd(varVector_t* vec, dict_t add) {
dictValue_t* var = NULL;
if (add.key != NULL)
var = varVectorFind(vec, add.key);
if (var != NULL) {
freeDictValue(*var);
*var = add.value;
free(add.key);
return;
}
if (vec->stored >= vec->len) {
vec->len *= 2;
dict_t* old = vec->vars;
//vec->vars = realloc(old, vec->len * sizeof(dict_t));
void *temp = calloc(vec->len, sizeof(dict_t));
memcpy(temp, vec->vars, vec->len / 2 * sizeof(dict_t));
free(vec->vars);
vec->vars = temp;
if (vec->vars == NULL) {
free(old);
}
}
vec->vars[vec->stored] = add;
vec->stored++;
}
void varVectorFree(varVector_t* vec) {
for (int i = 0; i < vec->stored; i++) {
dict_t *var = &vec->vars[i];
if (var->key != NULL) {
free(var->key);
var->key = NULL;
}
if (var->value.free)
freeDictValue(var->value);
}
free(vec->vars);
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "types.h"
#define dictValSetInt(dictVal, i) dictVal.integer = i; dictVal.type = IntType;
#define dictValSetStr(dictVal, str) dictVal.string = strdup(str); dictVal.type = StringType;
#define dictValSetJump(dictVal, i) dictVal.integer = i; dictVal.type = JumpType;
#define dictValInt(i) (dictValue_t) {IntType, 0, i}
#define DictCreate(key, value) (dict_t) {key, value}
#define DictValueCreate(type, arrayLen, val) (dictValue_t) {type, arrayLen, val}
void freeDictValue(dictValue_t dv);
void freeDict(dict_t* dict);
varVector_t varVectorInit(int startSize);
void varVectorAdd(varVector_t* vec, dict_t add);
dictValue_t* varVectorFind(varVector_t* vec, const char* key);
static inline void freeDictValueOnVar(dictValue_t dv) {
if (dv.free)
freeDictValue(dv);
}
void varVectorFree(varVector_t* vec);

View File

@ -1,307 +1,263 @@
#include "args.h"
#include "parser.h"
#include "types.h"
#include "list.h"
#include "functions.h"
#include "scriptCtx.h"
#include "lexer.h"
#include <string.h>
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../emmc/emmc.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../utils/sprintf.h"
#include "../../utils/btn.h"
#include "../../gfx/gfx.h"
#include "../../utils/util.h"
#include "../../storage/emummc.h"
#include "parser.h"
#include "../common/common.h"
#include "../fs/fsactions.h"
#include "functions.h"
#include "variables.h"
#include "../fs/fsreader.h"
#include "../utils/utils.h"
#include "../../storage/nx_sd.h"
#include "../../gfx/gfx.h"
#include "../../hid/hid.h"
#include "../gfx/gfxutils.h"
int countchars(const char* in, char target) {
u32 len = strlen(in);
u32 count = 0;
for (u32 i = 0; i < len; i++) {
if (in[i] == '"'){
while (in[++i] != '"'){
if (i >= len)
return -1;
}
}
if (in[i] == target)
count++;
}
//#define DPRINTF(str, ...) printf(str, __VA_ARGS__)
#define DPRINTF
return count;
#define findNextCharsCtx(ctx, targets) findNextChars(&(ctx->curPos), targets)
int checkIfVar(u16 token) {
return (token == StrLit || token == IntLit || token == Variable || token == RSBracket);
}
char **argv = NULL;
u32 argc;
u32 splitargs(const char* in) {
// arg like '5, "6", @arg7'
u32 i = 0, count = 1, len = strlen(in), curcount = 0, begin, end;
void printToken(lexarToken_t* token) {
switch (token->token) {
case 1:
gfx_printf("%s ", token->text);
break;
case 6:
//printf("%d: '%s'\n", vec.tokens[i].token, vec.tokens[i].text);
gfx_printf("\"%s\" ", token->text);
break;
case 7:
//printf("%d: %d\n", vec.tokens[i].token, vec.tokens[i].val);
gfx_printf("%d ", token->val);
break;
default:
//printf("%d: %c\n", vec.tokens[i].token, lexarDebugGetTokenC(vec.tokens[i].token));
gfx_printf("%c ", lexarDebugGetTokenC(token->token));
break;
}
}
count += countchars(in, ',');
scriptResult_t runFunction(scriptCtx_t* ctx) {
dictValue_t res = solveEquation(ctx, &ctx->script->tokens[ctx->startEq], ctx->curPos - ctx->startEq);
if (!count)
return 0;
argv = calloc(count + 1, sizeof(char*));
while (i < len && curcount < count) {
if (in[i] == ' ' || in[i] == ','){
i++;
continue;
}
begin = i;
if (res.varType == ErrType)
return scriptResultCreate(res.integer, &ctx->script->tokens[ctx->startEq]);
while (strrchr(" ,)", in[i]) == NULL){
if (in[i] == '"'){
begin = i + 1;
while (in[++i] != '"'){
if (in[i] == '\0')
return 0;
ctx->startEq = ctx->curPos;
if (ctx->varToken.token != Invalid) { // we should not assign null's
ctx->varToken.token = Invalid;
if (ctx->varIndexSet) {
ctx->varIndexSet = 0;
dictValue_t* arrayVal = varVectorFind(&ctx->vars, ctx->varToken.text);
if (!(arrayVal == NULL || arrayVal->arrayLen <= ctx->varIndex)) {
if (arrayVal->varType == IntArrayType && res.varType == IntType) {
arrayVal->integerArray[ctx->varIndex] = res.integer;
}
else if (arrayVal->varType == StringArrayType && res.varType == StringType) {
free(arrayVal->stringArray[ctx->varIndex]);
arrayVal->stringArray[ctx->varIndex] = res.string;
}
else if (arrayVal->varType == ByteArrayType && res.varType == IntType) {
arrayVal->byteArray[ctx->varIndex] = (u8)(res.integer & 0xFF);
}
else {
return scriptResultCreate(ERRINVALIDTYPE, &ctx->script->tokens[ctx->startEq]);
}
}
else {
return scriptResultCreate(ERRNOVAR, &ctx->script->tokens[ctx->startEq]);
}
}
else {
varVectorAdd(&ctx->vars, DictCreate(util_cpyStr(ctx->varToken.text), res));
}
}
else {
freeDictValueOnVar(res);
}
if (in[i] == '\0')
return 0;
return scriptResultCreate(0, 0);
}
// TODO
// Make sure mem gets free'd properly
// Fix bug that custom functions cannot be run from end of script
// add arrays
#define RUNFUNCWITHPANIC(ctx) scriptResult_t res = runFunction(ctx); if (res.resCode != 0) return res
scriptResult_t mainLoop(scriptCtx_t* ctx) {
for (ctx->curPos = 0; ctx->curPos < ctx->script->stored; ctx->curPos++) {
u32 i = ctx->curPos;
lexarToken_t curToken = ctx->script->tokens[i];
//printToken(&curToken);
if (checkIfVar(ctx->lastToken.token) && curToken.token == Variable) {
RUNFUNCWITHPANIC(ctx);
}
else if (curToken.token == Equal) {
// Set last var to lastToken, if lastToken is var
if (ctx->lastToken.token == RSBracket) {
int layer = 0;
i = ctx->lastTokenPos - 1;
for (; i > 0; i--) {
if (ctx->script->tokens[i].token == RSBracket)
layer++;
else if (ctx->script->tokens[i].token == LSBracket) {
if (layer == 0)
break;
layer--;
}
}
i--;
if (ctx->script->tokens[i].token == Variable) {
dictValue_t index = solveEquation(ctx, &ctx->script->tokens[i + 2], ctx->lastTokenPos - i - 2);
ctx->lastTokenPos = i;
ctx->lastToken = ctx->script->tokens[i];
if (index.varType == IntType) {
ctx->varIndex = index.integer;
ctx->varIndexSet = 1;
if (ctx->varIndexSet) {
dictValue_t* arrayVal = varVectorFind(&ctx->vars, ctx->varToken.text);
if (arrayVal == NULL) {
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
if (ctx->varIndex < 0 || ctx->varIndex >= arrayVal->arrayLen || arrayVal->varType < IntArrayType)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
}
else
return scriptResultCreate(ERRINVALIDTYPE, &ctx->script->tokens[ctx->curPos]);
}
else
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
if (ctx->lastToken.token == Variable) {
ctx->startEq = ctx->curPos + 1;
ctx->varToken = ctx->lastToken;
}
else
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
//printf("Setting token %s to next assignment", ctx->lastToken.text);
// !! check prev for ] for arrays
}
else if (curToken.token == LBracket) {
i++;
}
int distance = distanceBetweenTokens(&ctx->script->tokens[i], ctx->script->stored - i, LBracket, RBracket);
if (distance < 0)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
end = i;
i += distance;
ctx->curPos = i;
if (in[i - 1] == '"'){
end--;
}
argv[curcount++] = utils_copyStringSize(in + begin, (u32)(end - begin));
}
return curcount;
}
FIL scriptin;
UINT endByte = 0;
int forceExit = false;
char currentchar = 0;
char getnextchar(){
f_read(&scriptin, &currentchar, sizeof(char), &endByte);
if (sizeof(char) != endByte)
forceExit = true;
//gfx_printf("|%c|", currentchar);
return currentchar;
}
void getfollowingchar(char end){
while (currentchar != end && !f_eof(&scriptin)){
if (currentchar == '"'){
while (getnextchar() != '"' && !f_eof(&scriptin));
}
getnextchar();
}
}
void getnextvalidchar(){
while ((!((currentchar >= '?' && currentchar <= 'Z') || (currentchar >= 'a' && currentchar <= 'z') || currentchar == '#') && !f_eof(&scriptin)) /*|| currentchar == ';' */)
getnextchar();
}
char *makestr(u32 size, char ignore){
char *str;
u32 count = 0;
str = calloc(size + 1, sizeof(char));
for (u32 i = 0; i < size; i++){
getnextchar();
if (ignore != 0 && ignore == currentchar)
if (ctx->curPos + 1 >= ctx->script->stored && checkIfVar(ctx->lastToken.token)) {
solveEquation(ctx, &ctx->script->tokens[ctx->startEq], i + 1 - ctx->startEq);
}
continue;
str[count++] = currentchar;
}
return str;
}
}
else if (curToken.token == LCBracket) {
if (ctx->lastToken.token == Equal && ctx->varToken.token == Variable) {
varVectorAdd(&ctx->vars, DictCreate(util_cpyStr(ctx->varToken.text), DictValueCreate(JumpType, 0, ctx->curPos)));
ctx->varToken.token = Invalid;
setCurIndentInstruction(ctx, 1, -1);
}
char *readtilchar(char end, char ignore){
FSIZE_t offset, size;
if (checkIfVar(ctx->lastToken.token)) {
RUNFUNCWITHPANIC(ctx);
}
offset = f_tell(&scriptin);
getfollowingchar(end);
size = f_tell(&scriptin) - offset;
ctx->startEq = ctx->curPos + 1;
if (size <= 0)
return NULL;
indentInstructor_t ins = getCurIndentInstruction(ctx);
if (ins.active) {
if (ins.skip) {
int distance = distanceBetweenTokens(&ctx->script->tokens[i + 1], ctx->script->stored - i - 1, LCBracket, RCBracket);
if (distance < 0)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
ctx->curPos += distance + 1;
ctx->startEq = ctx->curPos + 1;
}
else {
ctx->indentLevel++;
}
}
else
return scriptResultCreate(ERRINACTIVEINDENT, &ctx->script->tokens[ctx->curPos]);
}
else if (curToken.token == RCBracket) {
if (checkIfVar(ctx->lastToken.token)) {
RUNFUNCWITHPANIC(ctx);
if (i != ctx->curPos)
continue;
}
f_lseek(&scriptin, offset - 1);
ctx->indentLevel--;
return makestr((u32)size, ignore);
}
indentInstructor_t ins = getCurIndentInstruction(ctx);
if (ins.active && ins.jump) {
ctx->curPos = ins.jumpLoc - 1;
}
char *funcbuff = NULL;
void functionparser(){
char *unsplitargs;
/*
if (funcbuff != NULL)
free(funcbuff);
*/
funcbuff = readtilchar('(', ' ');
getfollowingchar('(');
getnextchar();
unsplitargs = readtilchar(')', 0);
if (unsplitargs != NULL){
argc = splitargs(unsplitargs);
getnextchar();
}
else {
argc = 0;
}
getnextchar();
free(unsplitargs);
}
char *gettargetvar(){
char *variable = NULL;
variable = readtilchar('=', ' ');
getfollowingchar('=');
getnextchar();
return variable;
}
void mainparser(){
char *variable = NULL;
int res, out = 0;
getnextvalidchar();
if (f_eof(&scriptin))
return;
if (currentchar == '#'){
getfollowingchar('\n');
return;
}
if (currentchar == '@'){
variable = gettargetvar();
getnextvalidchar();
}
functionparser();
res = run_function(funcbuff, &out);
if (res < 0){
printerrors = true;
//gfx_printf("%s|%s|%d", funcbuff, argv[0], argc);
//btn_wait();
int lineNumber = 1;
u64 end = f_tell(&scriptin);
f_lseek(&scriptin, 0);
while (f_tell(&scriptin) < end && !f_eof(&scriptin)){
if (getnextchar() == '\n')
lineNumber++;
ctx->startEq = ctx->curPos + 1;
}
else if (ctx->curPos + 1 >= ctx->script->stored && checkIfVar(ctx->lastToken.token)) {
solveEquation(ctx, &ctx->script->tokens[ctx->startEq], i + 1 - ctx->startEq);
}
gfx_errDisplay((res == -1) ? funcbuff : "run_function", (res == -1) ? ERR_IN_FUNC : ERR_SCRIPT_LOOKUP_FAIL, lineNumber);
forceExit = true;
//gfx_printf("Func: %s\nArg1: %s\n", funcbuff, argv[0]);
}
else {
str_int_add("@RESULT", out);
if (variable != NULL)
str_int_add(variable, out);
ctx->lastToken = ctx->script->tokens[ctx->curPos];
ctx->lastTokenPos = ctx->curPos;
}
//gfx_printf("\nGoing to next func %c\n", currentchar);
if (funcbuff != NULL){
free(funcbuff);
funcbuff = NULL;
}
if (argv != NULL) {
for (int i = 0; argv[i] != NULL; i++)
free(argv[i]);
free(argv);
argv = NULL;
}
if (variable != NULL){
free(variable);
}
return scriptResultCreate(0, 0);
}
void skipbrackets(){
u32 bracketcounter = 0;
const char* functionFails[] = {
"An invalid operation was performed",
"Double Nots are not allowed",
"A syntax error was found",
"The recieved type was incorrect",
"The variable could not be found",
"The specified function could not be found",
"An inactive indent was found"
};
getfollowingchar('{');
getnextchar();
void startScript(char* path) {
char* file = sd_file_read(path, NULL);
while ((currentchar != '}' || bracketcounter != 0) && !f_eof(&scriptin)){
if (currentchar == '{')
bracketcounter++;
else if (currentchar == '}')
bracketcounter--;
getnextchar();
}
}
extern u32 currentcolor;
extern char *currentpath;
void runScript(char *path){
int res;
char *path_local = NULL;
forceExit = false;
currentchar = 0;
currentcolor = COLOR_WHITE;
gfx_clearscreen();
utils_copystring(path, &path_local);
res = f_open(&scriptin, path, FA_READ | FA_OPEN_EXISTING);
if (res != FR_OK){
gfx_errDisplay("ParseScript", res, 1);
if (file == NULL)
return;
gfx_clearscreen();
scriptCtx_t ctx = createScriptCtx();
lexarVector_t vec = lexarGo(file);
free(file);
ctx.script = &vec;
scriptResult_t res = mainLoop(&ctx);
gfx_printf("end of script\n");
if (res.resCode) {
gfx_printf("[ERROR] %d\n%s\nNear:", res.resCode, functionFails[res.resCode - 1]);
printToken(res.nearToken);
}
printerrors = false;
//add builtin vars
str_int_add("@EMUMMC", emu_cfg.enabled);
str_int_add("@RESULT", 0);
str_int_add("@JOYCONN", hidConnected());
str_str_add("$CURRENTPATH", currentpath);
//str_int_printall();
while (!f_eof(&scriptin) && !forceExit){
mainparser();
}
printerrors = true;
//str_int_printall();
f_close(&scriptin);
str_int_clear();
//str_jmp_clear();
str_str_clear();
free(path_local);
//btn_wait();
gfx_printf("\n\n");
//mainLoop2(&ctx, &vec);
lexarVectorClear(&vec);
destroyScriptCtx(&ctx);
hidWait();
}

View File

@ -1,7 +1,9 @@
#pragma once
#define INFUNC_FAIL (int)0xC0000000
#include "types.h"
//#define DictValue(type, val, len) (dictValue_t) {type, len, val}
void runScript(char *path);
void skipbrackets();
void getfollowingchar(char end);
#define scriptResultCreate(resCode, funcName) (scriptResult_t) {resCode, funcName}
void startScript(char* path);
char* readFile(char* path);

View File

@ -0,0 +1,37 @@
#include "scriptCtx.h"
#include "list.h"
#include "malloc.h"
#include "types.h"
scriptCtx_t createScriptCtx() {
scriptCtx_t ctx;
ctx.indentInstructors = calloc(sizeof(indentInstructor_t), 64);
ctx.indentLevel = 0;
ctx.vars = varVectorInit(16);
ctx.script = NULL;
ctx.lastToken.token = 0;
ctx.varToken.token = 0;
ctx.startEq = 0;
ctx.varIndexStruct = 0;
return ctx;
}
void destroyScriptCtx(scriptCtx_t* ctx) {
// TODO
varVectorFree(&ctx->vars);
free(ctx->indentInstructors);
}
u8 setIndentInstruction(scriptCtx_t* ctx, u8 level, u8 skip, int jumpLoc) {
if (level >= 64)
return 1;
ctx->indentInstructors[level].skip = skip;
ctx->indentInstructors[level].active = 1;
ctx->indentInstructors[level].jump = (jumpLoc >= 0) ? 1 : 0;
ctx->indentInstructors[level].jumpLoc = jumpLoc;
return 0;
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "types.h"
#define TEXTHOLDEREMPTY() (textHolder_t) {0}
#define TEXTHOLDER(start, len) (textHolder_t) {start, len, 1}
u8 setIndentInstruction(scriptCtx_t* ctx, u8 level, u8 skip, int jumpLoc);
void destroyScriptCtx(scriptCtx_t* ctx);
scriptCtx_t createScriptCtx();
static inline indentInstructor_t getCurIndentInstruction(scriptCtx_t* ctx);
static inline u8 setCurIndentInstruction(scriptCtx_t* ctx, u8 skip, int jumpLoc);
static inline u8 setCurIndentInstruction(scriptCtx_t* ctx, u8 skip, int jumpLoc) {
return setIndentInstruction(ctx, ctx->indentLevel, skip, jumpLoc);
}
static inline indentInstructor_t getCurIndentInstruction(scriptCtx_t* ctx) {
return ctx->indentInstructors[ctx->indentLevel];
}

View File

@ -0,0 +1,174 @@
#pragma once
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef struct {
u16 token;
union {
char* text;
int val;
};
} lexarToken_t;
typedef struct {
lexarToken_t* tokens;
u32 len;
u32 stored;
} lexarVector_t;
enum Tokens {
Invalid = 0,
Variable = 1,
LBracket,
RBracket,
RCBracket,
LCBracket,
StrLit,
IntLit,
Seperator,
Plus,
Minus,
Multiply,
Division,
Mod,
Smaller,
SmallerEqual,
Bigger,
BiggerEqual,
Equal,
EqualEqual,
Not,
NotEqual,
LogicAND,
LogicOR,
LSBracket,
RSBracket,
AND,
OR
};
enum Errors {
ERRBADOPERATOR = 1,
ERRDOUBLENOT,
ERRSYNTAX,
ERRINVALIDTYPE,
ERRNOVAR,
ERRNOFUNC,
ERRINACTIVEINDENT
};
typedef struct { // this is to keep track of how many {} we passed. Keep an internal var with the "indentation level", +1 for {, -1 for }. have an array with the following def on what to do (on func: enter, set indentation & jump back, on while, jump to while, use while as if, on if simply set true or false)
union {
struct {
u8 active : 1;
u8 skip : 1;
u8 jump : 1;
};
u8 container;
};
int jumpLoc;
} indentInstructor_t;
typedef struct {
char* start;
u32 len;
union {
struct {
u8 set : 1;
};
u8 options;
};
} textHolder_t;
typedef struct {
int resCode;
lexarToken_t* nearToken;
} scriptResult_t;
#define JumpDictValue(jump) (dictValue_t) {{JumpType}, 0, .integer = jump}
#define StrDictValue(str) (dictValue_t) {{StringType}, 0, .string = str}
#define ErrDictValue(err) (dictValue_t) {{ErrType}, 0, .integer = err}
#define NullDictValue() (dictValue_t) {{NullType}, 0, .integer = 0}
#define IntArrDictValue(arr, len) (dictValue_t) {{IntArrayType}, len, .integerArray = arr}
#define StringArrDictValue(arr, len) (dictValue_t) {{StringArrayType}, len, .stringArray = arr}
#define IntDictValue(i) (dictValue_t) {{IntType}, 0, .integer = i}
enum {
IntType = 0,
StringType,
IntArrayType,
StringArrayType,
ByteArrayType,
JumpType,
DictType,
NullType,
ErrType,
};
typedef struct {
union {
u8 type;
struct {
u8 varType : 7;
u8 free : 1;
};
};
unsigned int arrayLen;
union {
int integer;
char* string;
unsigned char* byteArray;
int* integerArray;
char** stringArray;
};
} dictValue_t;
typedef struct {
char* key;
dictValue_t value;
} dict_t;
typedef struct {
dict_t* vars;
u32 len;
u32 stored;
} varVector_t;
typedef struct {
indentInstructor_t* indentInstructors;
u8 indentLevel; // -> max 63
varVector_t vars;
lexarVector_t* script;
lexarToken_t lastToken;
lexarToken_t varToken;
u32 startEq;
u32 curPos;
u32 lastTokenPos;
lexarVector_t args_loc;
union {
u32 varIndexStruct;
struct {
u32 varIndex : 31;
u32 varIndexSet : 1;
};
};
} scriptCtx_t;
typedef dictValue_t(*func_int_ptr)(scriptCtx_t* ctx, varVector_t* args);
typedef struct {
char* key;
func_int_ptr value;
union {
u8 args;
struct {
u8 argCount : 6;
u8 varArgs : 1;
u8 operatorParse : 1;
};
};
} str_fnc_struct;
#define FREEINDICT 0x80

View File

@ -1,250 +0,0 @@
#include <string.h>
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../emmc/emmc.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../utils/sprintf.h"
#include "../../utils/btn.h"
#include "../../gfx/gfx.h"
#include "../../utils/util.h"
#include "../../storage/emummc.h"
#include "parser.h"
#include "../common/common.h"
#include "../fs/fsactions.h"
#include "variables.h"
#include "../utils/utils.h"
static dict_str_int *str_int_table = NULL;
static dict_str_str *str_str_table = NULL;
//static dict_str_loc *str_jmp_table = NULL;
int str_int_add(char *key, int value){
char *key_local;
dict_str_int *keyvaluepair;
utils_copystring(key, &key_local);
keyvaluepair = calloc(1, sizeof(dict_str_int));
keyvaluepair->key = key_local;
keyvaluepair->value = value;
keyvaluepair->next = NULL;
if (str_int_table == NULL){
str_int_table = keyvaluepair;
}
else {
dict_str_int *temp;
temp = str_int_table;
while (temp != NULL){
if (!strcmp(temp->key, key_local)){
free(keyvaluepair);
free(key_local);
temp->value = value;
return 0;
}
if (temp->next == NULL){
temp->next = keyvaluepair;
return 0;
}
temp = temp->next;
}
}
return 0;
}
int str_int_find(char *key, int *out){
dict_str_int *temp;
temp = str_int_table;
while (temp != NULL){
if (!strcmp(temp->key, key)){
*out = temp->value;
return 0;
}
temp = temp->next;
}
return -1;
}
void str_int_clear(){
dict_str_int *cur, *next;
cur = str_int_table;
while (cur != NULL){
next = cur->next;
free(cur->key);
free(cur);
cur = next;
}
str_int_table = NULL;
}
void str_int_printall(){
dict_str_int *temp;
temp = str_int_table;
while (temp != NULL){
gfx_printf("%s -> %d\n", temp->key, temp->value);
temp = temp->next;
}
}
/*
int str_jmp_add(char *key, u64 value){
char *key_local;
dict_str_loc *keyvaluepair;
//gfx_printf("Adding |%s|\n", key_local);
utils_copystring(key, &key_local);
keyvaluepair = calloc(1, sizeof(dict_str_loc));
keyvaluepair->key = key_local;
keyvaluepair->value = value;
keyvaluepair->next = NULL;
if (str_jmp_table == NULL){
str_jmp_table = keyvaluepair;
}
else {
dict_str_loc *temp;
temp = str_jmp_table;
while (temp != NULL){
if (!strcmp(temp->key, key_local)){
free(keyvaluepair);
free(key_local);
temp->value = value;
return 0;
}
if (temp->next == NULL){
temp->next = keyvaluepair;
return 0;
}
temp = temp->next;
}
}
return 0;
}
int str_jmp_find(char *key, u64 *out){
dict_str_loc *temp;
temp = str_jmp_table;
//gfx_printf("Searching |%s|\n", key);
while (temp != NULL){
if (!strcmp(temp->key, key)){
//gfx_printf("Key found!\n", temp->value);
*out = temp->value;
return 0;
}
temp = temp->next;
}
//gfx_printf("no key!\n");
return -1;
}
void str_jmp_clear(){
dict_str_loc *cur, *next;
cur = str_jmp_table;
while (cur != NULL){
next = cur->next;
free(cur->key);
free(cur);
cur = next;
}
str_jmp_table = NULL;
}
*/
int str_str_add(char *key, char *value){
char *key_local, *value_local;
dict_str_str *keyvaluepair;
//gfx_printf("Adding |%s|\n", key_local);
utils_copystring(value, &value_local);
utils_copystring(key, &key_local);
keyvaluepair = calloc(1, sizeof(dict_str_str));
keyvaluepair->key = key_local;
keyvaluepair->value = value_local;
keyvaluepair->next = NULL;
if (str_str_table == NULL){
str_str_table = keyvaluepair;
}
else {
dict_str_str *temp;
temp = str_str_table;
while (temp != NULL){
if (!strcmp(temp->key, key_local)){
free(keyvaluepair);
free(key_local);
free(temp->value);
temp->value = value_local;
return 0;
}
if (temp->next == NULL){
temp->next = keyvaluepair;
return 0;
}
temp = temp->next;
}
}
return 0;
}
int str_str_find(char *key, char **out){
dict_str_str *temp;
temp = str_str_table;
while (temp != NULL){
if (!strcmp(temp->key, key)){
*out = temp->value;
return 0;
}
temp = temp->next;
}
return -1;
}
int str_str_index(int index, char **out){
dict_str_str *temp;
temp = str_str_table;
for (int i = 0; i < index; i++){
if (temp == NULL)
return -1;
temp = temp->next;
}
if (temp == NULL)
return -1;
*out = temp->value;
return 0;
}
void str_str_clear(){
dict_str_str *cur, *next;
cur = str_str_table;
while (cur != NULL){
next = cur->next;
free(cur->key);
free(cur->value);
free(cur);
cur = next;
}
str_str_table = NULL;
}

View File

@ -1,34 +0,0 @@
#pragma once
#include "../../utils/types.h"
typedef struct _dict_str_int {
char *key;
int value;
struct _dict_str_int *next;
} dict_str_int;
typedef struct _dict_str_str {
char *key;
char *value;
struct _dict_str_str *next;
} dict_str_str;
typedef struct _dict_str_loc {
char *key;
u64 value;
struct _dict_str_loc *next;
} dict_str_loc;
int str_int_add(char *key, int value);
int str_int_find(char *key, int *out);
void str_int_clear();
void str_int_printall();
/*
int str_jmp_add(char *key, u64 value);
int str_jmp_find(char *key, u64 *out);
void str_jmp_clear();
*/
int str_str_add(char *key, char *value);
int str_str_find(char *key, char **out);
int str_str_index(int index, char **out);
void str_str_clear();

View File

@ -202,4 +202,10 @@ char *utils_copyStringSize(const char *in, int size){
//strncpy(out, in, size);
memcpy(out, in, size);
return out;
}
char* util_cpyStr(const char* in){
char *out = malloc(strlen(in) + 1);
strcpy(out, in);
return out;
}

View File

@ -24,4 +24,5 @@ int utils_mmcMenu();
void utils_copystring(const char *in, char **out);
char *utils_InputText(char *start, int maxLen);
void utils_takeScreenshot();
char *utils_copyStringSize(const char *in, int size);
char *utils_copyStringSize(const char *in, int size);
char* util_cpyStr(const char* in);