# HG changeset patch # User Michael Pavone # Date 1490082025 25200 # Node ID 5905593d6828804c5216aa09076c35a8f3370ccb # Parent f17fe0d00626ae03bf89b252c5c8694f97de4981 Allow initial_path to contain variable references which allows the default value to be actually specified in the default config file diff -r f17fe0d00626 -r 5905593d6828 default.cfg --- a/default.cfg Sun Mar 19 18:32:49 2017 -0700 +++ b/default.cfg Tue Mar 21 00:40:25 2017 -0700 @@ -195,9 +195,12 @@ } ui { + #specifies the ROM that implements the Menu UI rom menu.bin - #initial_path defaults to your home/user profile directory if not specified - #screenshot_path behaves the same way + #starting path for ROM browsing, accepts special variables $HOME, $EXEDIR + #and variables defined in the OS environment + initial_path $HOME + #screenshot_path defaults to the user's home/profile directory if not specified #see strftime for the format specifiers valid in screenshot_template screenshot_template blastem_%c.ppm } diff -r f17fe0d00626 -r 5905593d6828 menu.c --- a/menu.c Sun Mar 19 18:32:49 2017 -0700 +++ b/menu.c Tue Mar 21 00:40:25 2017 -0700 @@ -167,15 +167,16 @@ if (!menu) { gen->extra = menu = calloc(1, sizeof(menu_context)); menu->curpath = tern_find_path(config, "ui\0initial_path\0").ptrval; - if (menu->curpath) { - menu->curpath = strdup(menu->curpath); - } else { + if (!menu->curpath){ #ifdef __ANDROID__ - menu->curpath = strdup(get_external_storage_path()); + menu->curpath = get_external_storage_path(); #else - menu->curpath = strdup(get_home_dir()); + menu->curpath = "$HOME"; #endif } + tern_node *vars = tern_insert_ptr(NULL, "HOME", get_home_dir()); + vars = tern_insert_ptr(vars, "EXEDIR", get_exe_dir()); + menu->curpath = replace_vars(menu->curpath, vars, 1); } if (menu->state) { uint32_t dst = menu->latch << 16 | value; diff -r f17fe0d00626 -r 5905593d6828 util.c --- a/util.c Sun Mar 19 18:32:49 2017 -0700 +++ b/util.c Tue Mar 21 00:40:25 2017 -0700 @@ -57,6 +57,92 @@ return ret; } +typedef struct { + uint32_t start; + uint32_t end; + char *value; +} var_pos; + +char *replace_vars(char *base, tern_node *vars, uint8_t allow_env) +{ + uint32_t num_vars = 0; + for (char *cur = base; *cur; ++cur) + { + //TODO: Support escaping $ and allow brace syntax + if (*cur == '$') { + num_vars++; + } + } + var_pos *positions = calloc(num_vars, sizeof(var_pos)); + num_vars = 0; + uint8_t in_var = 0; + uint32_t max_var_len = 0; + for (char *cur = base; *cur; ++cur) + { + if (in_var) { + if (!(*cur == '_' || isalnum(*cur))) { + positions[num_vars].end = cur-base; + if (positions[num_vars].end - positions[num_vars].start > max_var_len) { + max_var_len = positions[num_vars].end - positions[num_vars].start; + } + num_vars++; + in_var = 0; + } + } else if (*cur == '$') { + positions[num_vars].start = cur-base+1; + in_var = 1; + } + } + if (in_var) { + positions[num_vars].end = strlen(base); + if (positions[num_vars].end - positions[num_vars].start > max_var_len) { + max_var_len = positions[num_vars].end - positions[num_vars].start; + } + num_vars++; + } + char *varname = malloc(max_var_len+1); + uint32_t total_len = 0; + uint32_t cur = 0; + for (uint32_t i = 0; i < num_vars; i++) + { + total_len += (positions[i].start - 1) - cur; + cur = positions[i].start; + memcpy(varname, base + positions[i].start, positions[i].end-positions[i].start); + varname[positions[i].end-positions[i].start] = 0; + positions[i].value = tern_find_ptr(vars, varname); + if (!positions[i].value && allow_env) { + positions[i].value = getenv(varname); + } + if (positions[i].value) { + total_len += strlen(positions[i].value); + } + } + total_len += strlen(base+cur); + free(varname); + char *output = malloc(total_len+1); + cur = 0; + char *curout = output; + for (uint32_t i = 0; i < num_vars; i++) + { + if (positions[i].start-1 > cur) { + memcpy(curout, base + cur, (positions[i].start-1) - cur); + curout += (positions[i].start-1) - cur; + } + if (positions[i].value) { + strcpy(curout, positions[i].value); + curout += strlen(curout); + } + cur = positions[i].end; + }; + if (base[cur]) { + strcpy(curout, base+cur); + } else { + *curout = 0; + } + free(positions); + return output; +} + void byteswap_rom(int filesize, uint16_t *cart) { for(uint16_t *cur = cart; cur - cart < filesize/2; ++cur) diff -r f17fe0d00626 -r 5905593d6828 util.h --- a/util.h Sun Mar 19 18:32:49 2017 -0700 +++ b/util.h Tue Mar 21 00:40:25 2017 -0700 @@ -21,6 +21,8 @@ char * alloc_concat(char const * first, char const * second); //Allocates a new string containing the concatenation of the strings pointed to by parts char * alloc_concat_m(int num_parts, char const ** parts); +//Returns a newly allocated string in which all variables in based are replaced with values from vars or the environment +char *replace_vars(char *base, tern_node *vars, uint8_t allow_env); //Byteswaps a ROM image in memory void byteswap_rom(int filesize, uint16_t *cart); //Returns the size of a file using fseek and ftell