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_FOR 4
|
||||
|
||||
#define _MAX_FOR_DEPTH 16
|
||||
|
||||
#define VAR_BUFFER (SCRIPT_BUFFER + SCRIPT_BUFFER_SIZE - VAR_BUFFER_SIZE)
|
||||
|
||||
// macros for textviewer
|
||||
@ -130,7 +132,7 @@ Gm9ScriptCmd cmd_list[] = {
|
||||
{ CMD_ID_ELIF , _CMD_ELIF , 1, 0 },
|
||||
{ CMD_ID_ELSE , _CMD_ELSE , 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_GOTO , "goto" , 1, 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, "--no_cancel", len) == 0) flag_char = 'n';
|
||||
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, "--unequal", len) == 0) flag_char = 'u';
|
||||
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;
|
||||
}
|
||||
|
||||
bool for_handler(char* path, const char* dir, const char* pattern) {
|
||||
static DIR fdir;
|
||||
bool for_handler(char* path, const char* dir, const char* pattern, bool recursive) {
|
||||
static DIR fdir[_MAX_FOR_DEPTH];
|
||||
static DIR* dp = NULL;
|
||||
static char ldir[256];
|
||||
static char lpattern[64];
|
||||
static bool rec = false;
|
||||
|
||||
if (!path && !dir && !pattern) {
|
||||
if (dp) fvx_closedir(dp);
|
||||
if (!path && !dir && !pattern) { // close all dirs
|
||||
while (dp >= fdir) fvx_closedir(dp--);
|
||||
dp = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dir) {
|
||||
if (dir) { // open a dir
|
||||
snprintf(lpattern, 64, pattern);
|
||||
snprintf(ldir, 256, dir);
|
||||
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;
|
||||
dp = &fdir;
|
||||
} else if (dp) {
|
||||
dp = &fdir[0];
|
||||
rec = recursive;
|
||||
} else if (dp) { // traverse dir
|
||||
FILINFO fno;
|
||||
if ((fvx_preaddir(dp, &fno, lpattern) != FR_OK) || !*(fno.fname)) *path = '\0';
|
||||
else snprintf(path, 256, "%s/%.254s", ldir, fno.fname);
|
||||
while ((fvx_preaddir(dp, &fno, lpattern) != FR_OK) || !*(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;
|
||||
|
||||
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'");
|
||||
syntax_error = true;
|
||||
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");
|
||||
skip_state = _SKIP_TO_NEXT;
|
||||
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");
|
||||
ret = false;
|
||||
} else {
|
||||
if (!for_handler(var, NULL, NULL)) *var = '\0';
|
||||
if (!for_handler(var, NULL, NULL, false)) *var = '\0';
|
||||
if (!*var) {
|
||||
for_handler(NULL, NULL, NULL); // finish for_handler
|
||||
for_handler(NULL, NULL, NULL, false); // finish for_handler
|
||||
for_ptr = NULL;
|
||||
skip_state = 0;
|
||||
} else {
|
||||
@ -1708,7 +1725,7 @@ bool ExecuteGM9Script(const char* path_script) {
|
||||
ifcnt = 0; // jumping into conditional block is unexpected/unsupported
|
||||
jump_ptr = NULL;
|
||||
for_ptr = NULL;
|
||||
for_handler(NULL, NULL, NULL);
|
||||
for_handler(NULL, NULL, NULL, false);
|
||||
} else {
|
||||
ptr = line_end + 1;
|
||||
lno++;
|
||||
@ -1721,7 +1738,7 @@ bool ExecuteGM9Script(const char* path_script) {
|
||||
return false;
|
||||
} else if (for_ptr) {
|
||||
ShowPrompt(false, "%s\nend of script: unresolved 'for'", path_str);
|
||||
for_handler(NULL, NULL, NULL);
|
||||
for_handler(NULL, NULL, NULL, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,16 @@
|
||||
# GodMode9 "Spaghetti code sample"
|
||||
# Tutorial script - read / run this to learn how it works
|
||||
# last changed: 20171229
|
||||
# last changed: 20180118
|
||||
# author: d0k3
|
||||
|
||||
|
||||
# quick preview mode as default, otherwise slow
|
||||
set PREVIEW_MODE quick
|
||||
|
||||
|
||||
# choose example to try
|
||||
labelsel "Choose example" spaghetti_*
|
||||
labelsel -o -s "Choose example" spaghetti_*
|
||||
goto outside
|
||||
|
||||
|
||||
# if-else-elif-end sample code
|
||||
@ -61,6 +66,47 @@ goto outside
|
||||
|
||||
@chooser
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user