mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
Scripting: Allow recursive 'for'
This commit is contained in:
parent
3684db2fe7
commit
5034e99832
@ -41,6 +41,8 @@
|
|||||||
#define _SKIP_TO_NEXT 3
|
#define _SKIP_TO_NEXT 3
|
||||||
#define _SKIP_TO_FOR 4
|
#define _SKIP_TO_FOR 4
|
||||||
|
|
||||||
|
#define _MAX_FOR_DEPTH 16
|
||||||
|
|
||||||
#define VAR_BUFFER (SCRIPT_BUFFER + SCRIPT_BUFFER_SIZE - VAR_BUFFER_SIZE)
|
#define VAR_BUFFER (SCRIPT_BUFFER + SCRIPT_BUFFER_SIZE - VAR_BUFFER_SIZE)
|
||||||
|
|
||||||
// macros for textviewer
|
// macros for textviewer
|
||||||
@ -130,7 +132,7 @@ Gm9ScriptCmd cmd_list[] = {
|
|||||||
{ CMD_ID_ELIF , _CMD_ELIF , 1, 0 },
|
{ CMD_ID_ELIF , _CMD_ELIF , 1, 0 },
|
||||||
{ CMD_ID_ELSE , _CMD_ELSE , 0, 0 },
|
{ CMD_ID_ELSE , _CMD_ELSE , 0, 0 },
|
||||||
{ CMD_ID_END , _CMD_END , 0, 0 },
|
{ CMD_ID_END , _CMD_END , 0, 0 },
|
||||||
{ CMD_ID_FOR , _CMD_FOR , 2, 0 },
|
{ CMD_ID_FOR , _CMD_FOR , 2, _FLG('r') },
|
||||||
{ CMD_ID_NEXT , _CMD_NEXT , 0, 0 },
|
{ CMD_ID_NEXT , _CMD_NEXT , 0, 0 },
|
||||||
{ CMD_ID_GOTO , "goto" , 1, 0 },
|
{ CMD_ID_GOTO , "goto" , 1, 0 },
|
||||||
{ CMD_ID_LABELSEL, "labelsel", 2, 0 },
|
{ CMD_ID_LABELSEL, "labelsel", 2, 0 },
|
||||||
@ -508,6 +510,7 @@ u32 get_flag(char* str, u32 len, char* err_str) {
|
|||||||
else if (strncmp(str, "--legit", len) == 0) flag_char = 'l';
|
else if (strncmp(str, "--legit", len) == 0) flag_char = 'l';
|
||||||
else if (strncmp(str, "--no_cancel", len) == 0) flag_char = 'n';
|
else if (strncmp(str, "--no_cancel", len) == 0) flag_char = 'n';
|
||||||
else if (strncmp(str, "--optional", len) == 0) flag_char = 'o';
|
else if (strncmp(str, "--optional", len) == 0) flag_char = 'o';
|
||||||
|
else if (strncmp(str, "--recursive", len) == 0) flag_char = 'r';
|
||||||
else if (strncmp(str, "--silent", len) == 0) flag_char = 's';
|
else if (strncmp(str, "--silent", len) == 0) flag_char = 's';
|
||||||
else if (strncmp(str, "--unequal", len) == 0) flag_char = 'u';
|
else if (strncmp(str, "--unequal", len) == 0) flag_char = 'u';
|
||||||
else if (strncmp(str, "--overwrite", len) == 0) flag_char = 'w';
|
else if (strncmp(str, "--overwrite", len) == 0) flag_char = 'w';
|
||||||
@ -671,29 +674,43 @@ char* find_label(const char* label, const char* last_found) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool for_handler(char* path, const char* dir, const char* pattern) {
|
bool for_handler(char* path, const char* dir, const char* pattern, bool recursive) {
|
||||||
static DIR fdir;
|
static DIR fdir[_MAX_FOR_DEPTH];
|
||||||
static DIR* dp = NULL;
|
static DIR* dp = NULL;
|
||||||
static char ldir[256];
|
static char ldir[256];
|
||||||
static char lpattern[64];
|
static char lpattern[64];
|
||||||
|
static bool rec = false;
|
||||||
|
|
||||||
if (!path && !dir && !pattern) {
|
if (!path && !dir && !pattern) { // close all dirs
|
||||||
if (dp) fvx_closedir(dp);
|
while (dp >= fdir) fvx_closedir(dp--);
|
||||||
dp = NULL;
|
dp = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir) {
|
if (dir) { // open a dir
|
||||||
snprintf(lpattern, 64, pattern);
|
snprintf(lpattern, 64, pattern);
|
||||||
snprintf(ldir, 256, dir);
|
snprintf(ldir, 256, dir);
|
||||||
if (dp) return false; // <- this should never happen
|
if (dp) return false; // <- this should never happen
|
||||||
if (fvx_opendir(&fdir, dir) != FR_OK)
|
if (fvx_opendir(&fdir[0], dir) != FR_OK)
|
||||||
return false;
|
return false;
|
||||||
dp = &fdir;
|
dp = &fdir[0];
|
||||||
} else if (dp) {
|
rec = recursive;
|
||||||
|
} else if (dp) { // traverse dir
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
if ((fvx_preaddir(dp, &fno, lpattern) != FR_OK) || !*(fno.fname)) *path = '\0';
|
while ((fvx_preaddir(dp, &fno, lpattern) != FR_OK) || !*(fno.fname)) {
|
||||||
else snprintf(path, 256, "%s/%.254s", ldir, fno.fname);
|
*path = '\0';
|
||||||
|
if (dp == fdir) return true;
|
||||||
|
fvx_closedir(dp--);
|
||||||
|
char* slash = strrchr(ldir, '/');
|
||||||
|
if (!slash) return false;
|
||||||
|
*slash = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path, 256, "%s/%.254s", ldir, fno.fname);
|
||||||
|
if (rec && (fno.fattrib & AM_DIR) && (dp - fdir < _MAX_FOR_DEPTH - 1)) {
|
||||||
|
if (fvx_opendir(++dp, path) != FR_OK) dp--;
|
||||||
|
else strncpy(ldir, path, 255);
|
||||||
|
}
|
||||||
} else return false;
|
} else return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -833,7 +850,7 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
|
|||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "'for' inside 'for'");
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "'for' inside 'for'");
|
||||||
syntax_error = true;
|
syntax_error = true;
|
||||||
return false;
|
return false;
|
||||||
} else if (!for_handler(NULL, argv[0], argv[1])) {
|
} else if (!for_handler(NULL, argv[0], argv[1], flags & _FLG('r'))) {
|
||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "dir not found");
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "dir not found");
|
||||||
skip_state = _SKIP_TO_NEXT;
|
skip_state = _SKIP_TO_NEXT;
|
||||||
ret = false;
|
ret = false;
|
||||||
@ -854,9 +871,9 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
|
|||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "forpath error");
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "forpath error");
|
||||||
ret = false;
|
ret = false;
|
||||||
} else {
|
} else {
|
||||||
if (!for_handler(var, NULL, NULL)) *var = '\0';
|
if (!for_handler(var, NULL, NULL, false)) *var = '\0';
|
||||||
if (!*var) {
|
if (!*var) {
|
||||||
for_handler(NULL, NULL, NULL); // finish for_handler
|
for_handler(NULL, NULL, NULL, false); // finish for_handler
|
||||||
for_ptr = NULL;
|
for_ptr = NULL;
|
||||||
skip_state = 0;
|
skip_state = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -1708,7 +1725,7 @@ bool ExecuteGM9Script(const char* path_script) {
|
|||||||
ifcnt = 0; // jumping into conditional block is unexpected/unsupported
|
ifcnt = 0; // jumping into conditional block is unexpected/unsupported
|
||||||
jump_ptr = NULL;
|
jump_ptr = NULL;
|
||||||
for_ptr = NULL;
|
for_ptr = NULL;
|
||||||
for_handler(NULL, NULL, NULL);
|
for_handler(NULL, NULL, NULL, false);
|
||||||
} else {
|
} else {
|
||||||
ptr = line_end + 1;
|
ptr = line_end + 1;
|
||||||
lno++;
|
lno++;
|
||||||
@ -1721,7 +1738,7 @@ bool ExecuteGM9Script(const char* path_script) {
|
|||||||
return false;
|
return false;
|
||||||
} else if (for_ptr) {
|
} else if (for_ptr) {
|
||||||
ShowPrompt(false, "%s\nend of script: unresolved 'for'", path_str);
|
ShowPrompt(false, "%s\nend of script: unresolved 'for'", path_str);
|
||||||
for_handler(NULL, NULL, NULL);
|
for_handler(NULL, NULL, NULL, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
# GodMode9 "Spaghetti code sample"
|
# GodMode9 "Spaghetti code sample"
|
||||||
# Tutorial script - read / run this to learn how it works
|
# Tutorial script - read / run this to learn how it works
|
||||||
# last changed: 20171229
|
# last changed: 20180118
|
||||||
# author: d0k3
|
# author: d0k3
|
||||||
|
|
||||||
|
|
||||||
|
# quick preview mode as default, otherwise slow
|
||||||
|
set PREVIEW_MODE quick
|
||||||
|
|
||||||
|
|
||||||
# choose example to try
|
# choose example to try
|
||||||
labelsel "Choose example" spaghetti_*
|
labelsel -o -s "Choose example" spaghetti_*
|
||||||
|
goto outside
|
||||||
|
|
||||||
|
|
||||||
# if-else-elif-end sample code
|
# if-else-elif-end sample code
|
||||||
@ -61,6 +66,47 @@ goto outside
|
|||||||
|
|
||||||
@chooser
|
@chooser
|
||||||
labelsel -o -s "Choose preview mode" choice_*
|
labelsel -o -s "Choose preview mode" choice_*
|
||||||
goto chooser
|
goto outside
|
||||||
|
|
||||||
|
|
||||||
|
# for-next sample code
|
||||||
|
@spaghetti_fornext_sample
|
||||||
|
|
||||||
|
echo "This will display entries\nfrom your SD card root."
|
||||||
|
|
||||||
|
if ask "Use recursive 'for'?"
|
||||||
|
for -r 0: *
|
||||||
|
# check type of current entry
|
||||||
|
set TYPE "File"
|
||||||
|
if isdir $[FORPATH]
|
||||||
|
set TYPE "Dir"
|
||||||
|
end
|
||||||
|
|
||||||
|
# output on screen
|
||||||
|
if not ask "$[TYPE]: $[FORPATH]\nShow next entry?"
|
||||||
|
goto outside
|
||||||
|
end
|
||||||
|
next
|
||||||
|
else
|
||||||
|
for 0: * # everything inside the loop pretty much identical to above
|
||||||
|
# check type of current entry
|
||||||
|
set TYPE "File"
|
||||||
|
if isdir $[FORPATH]
|
||||||
|
set TYPE "Dir"
|
||||||
|
end
|
||||||
|
|
||||||
|
# output on screen
|
||||||
|
if not ask "$[TYPE]: $[FORPATH]\nShow next entry?"
|
||||||
|
goto outside
|
||||||
|
end
|
||||||
|
|
||||||
|
if not exist $[FORPATH]
|
||||||
|
echo "WTF" # can never happen here, just a demonstration
|
||||||
|
end
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
goto outside
|
||||||
|
|
||||||
|
|
||||||
@outside
|
@outside
|
||||||
|
Loading…
x
Reference in New Issue
Block a user