From ca77091d63b3600b7a3829db8ae24c765c65440d Mon Sep 17 00:00:00 2001 From: Louie Shprung Date: Mon, 19 Aug 2024 20:44:56 -0400 Subject: Ability to set entry attributes --- src/read_cfg.c | 291 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 207 insertions(+), 84 deletions(-) diff --git a/src/read_cfg.c b/src/read_cfg.c index 3b8d24a..6c334ac 100644 --- a/src/read_cfg.c +++ b/src/read_cfg.c @@ -24,12 +24,13 @@ //private //void check_line(char *buffer, char **options, int ln); //int check_option(char *arg, char **options); -void get_settings(lua_State *L, int table_stack_index); // gets settings from Settings global variable -int get_group_count(lua_State *L, int table_stack_index); // counts the number of valid groups -int get_entry_count(lua_State *L, int table_stack_index); // counts the number of valid entries for a group -void add_groups(lua_State *L, int table_stack_index, GROUP ***g); -void add_entries(lua_State *L, int table_stack_index, GROUP *g); +void get_settings(lua_State *L); // gets settings from Settings global variable +int get_group_count(lua_State *L); // counts the number of valid groups +int get_entry_count(lua_State *L); // counts the number of valid entries for a group +void add_groups(lua_State *L, GROUP ***g); +void add_entries(lua_State *L, GROUP *g); void stack_debug(lua_State *L); +void table_debug(lua_State *L, int print_depth); //turn on or off sorting for entries (A-Z); On by default // TODO allow specifying whether to sort groups or entries (or both, or none) @@ -55,6 +56,7 @@ GROUP **cfg_interp(char *path, int *group_count){ // load lua configuration lua_State *L = luaL_newstate(); + // new lua stack luaL_openlibs(L); // allow for standard library to be used int config_load_status = luaL_dofile(L, path); if(config_load_status != 0) { @@ -71,23 +73,24 @@ GROUP **cfg_interp(char *path, int *group_count){ // open Settings table lua_getglobal(L, "Settings"); - i = lua_gettop(L); - if(lua_type(L, i) == LUA_TTABLE) { + // stack now contains: -1 => Settings + if(lua_type(L, -1) == LUA_TTABLE) { // parse settings - get_settings(L, i); + get_settings(L); } - lua_pop(L, lua_gettop(L)); + lua_pop(L, 1); + // empty stack // open Groups table lua_getglobal(L, "Groups"); - i = lua_gettop(L); - if(lua_type(L, i) != LUA_TTABLE) { - printf("Error in config: 'Groups' should be Table, is actually %s\n", lua_typename(L, lua_type(L, i))); + // stack now contains: -1 => Groups + if(lua_type(L, -1) != LUA_TTABLE) { + printf("Error in config: 'Groups' should be Table, is actually %s\n", lua_typename(L, lua_type(L, -1))); exit(1); } // create the group array - *group_count = get_group_count(L, i); + *group_count = get_group_count(L); if(*group_count <= 0) { printf("Error: No Groups!\n"); g = NULL; @@ -96,7 +99,7 @@ GROUP **cfg_interp(char *path, int *group_count){ g = malloc(sizeof(GROUP *) * (*group_count)); // add each group (which also adds each entry to each group) - add_groups(L, i, &g); + add_groups(L, &g); } lua_close(L); return g; @@ -107,7 +110,9 @@ void refer_to_doc(){ return; } -void get_settings(lua_State *L, int table_stack_index) { +void get_settings(lua_State *L) { + // stack now contains: -1 => table + bool *setting_vars[] = { &sort }; @@ -124,60 +129,87 @@ void get_settings(lua_State *L, int table_stack_index) { // check if autoAlias is set for(i = 0; i < count; ++i) { lua_pushstring(L, setting_strings[i]); - lua_gettable(L, table_stack_index); + // stack now contains: -1 => setting_string; -2 => table + lua_gettable(L, -2); + // stack now contains: -1 => string_value; -2 => table if(lua_type(L, -1) == LUA_TBOOLEAN) { *(setting_vars[i]) = lua_toboolean(L, -1); } + lua_pop(L, 1); + // stack now contains: -1 => table } } -int get_group_count(lua_State *L, int table_stack_index) { - int i = 1; +int get_group_count(lua_State *L) { int output = 0; - int group_table_stack_index; - int entry_table_stack_index; - const char *group_name; - do { - lua_rawgeti(L, table_stack_index, i); - group_table_stack_index = lua_gettop(L); - if(lua_type(L, group_table_stack_index) == LUA_TTABLE) { - // check validity of this group + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(lua_type(L, -1) == LUA_TNUMBER && lua_type(L, -2) == LUA_TTABLE) { lua_pushstring(L, "name"); - lua_gettable(L, group_table_stack_index); - group_name = lua_tostring(L, -1); - if(group_name != NULL) { + // stack now contains: -1 => "name"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table + if(lua_type(L, -1) == LUA_TSTRING) { // check that the Entries table for this group is not empty lua_pushstring(L, "Entries"); - lua_gettable(L, group_table_stack_index); - entry_table_stack_index = lua_gettop(L); - if(lua_type(L, entry_table_stack_index) == LUA_TTABLE - && get_entry_count(L, entry_table_stack_index) > 0) + // stack now contains: -1 => "Entries"; -2 => name; -3 => key; -4 => value; -5 => key; -6 => table + lua_gettable(L, -4); + // stack now contains: -1 => Entries; -2 => name; -3 => key; -4 => value; -5 => key; -6 => table + if(lua_type(L, -1) == LUA_TTABLE && get_entry_count(L) > 0) ++output; + lua_pop(L, 1); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table } + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table } - ++i; - } while(lua_type(L, group_table_stack_index) != LUA_TNIL); + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table + } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key + // but does not push anything.) - lua_pop(L, lua_gettop(L)-table_stack_index-1); return output; } -int get_entry_count(lua_State *L, int table_stack_index) { - int i = 1; +int get_entry_count(lua_State *L) { int output = 0; - do { - lua_rawgeti(L, table_stack_index, i); - if(lua_type(L, -1) == LUA_TSTRING) ++output; - ++i; - } while(lua_type(L, -1) != LUA_TNIL); + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(lua_type(L, -1) == LUA_TNUMBER && lua_type(L, -2) == LUA_TTABLE) { + // check that the entry has a valid name + lua_pushstring(L, "name"); + // stack now contains: -1 => "name"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table + if(lua_type(L, -1) == LUA_TSTRING) ++output; + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + } + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table + } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key + // but does not push anything.) - lua_pop(L, lua_gettop(L)-table_stack_index-1); return output; } -void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { +void add_groups(lua_State *L, GROUP ***g) { const char *group_name; int group_table_stack_index; // index of Groups.TABLE_NAME int entry_table_stack_index; // index of Groups.TABLE_NAME.Entries @@ -186,92 +218,136 @@ void add_groups(lua_State *L, int table_stack_index, GROUP ***g) { int i = 1; // index in lua table int count = 0; // index in C struct - // sort the groups, if necessary - if(sort) { - luaL_dostring(L, "table.sort(Groups)"); - } - - do { - lua_rawgeti(L, table_stack_index, i); - group_table_stack_index = lua_gettop(L); - if(lua_type(L, group_table_stack_index) == LUA_TTABLE) { - // check validity of this group + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(lua_type(L, -1) == LUA_TNUMBER && lua_type(L, -2) == LUA_TTABLE) { lua_pushstring(L, "name"); - lua_gettable(L, group_table_stack_index); + // stack now contains: -1 => "name"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table group_name = lua_tostring(L, -1); + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table if(group_name != NULL) { // push the Entries table on the stack (to get entry information) lua_pushstring(L, "Entries"); - - // get table Groups[i].Entries - lua_gettable(L, group_table_stack_index); - entry_table_stack_index = lua_gettop(L); - - // check that 'Entries' is a table - if(lua_type(L, entry_table_stack_index) != LUA_TTABLE) { - printf("Error in config: in group '%s': 'Entries' should be Table, is actually %s\n", group_name, lua_typename(L, lua_type(L, entry_table_stack_index))); + // stack now contains: -1 => "Entries"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => Entries; -2 => key; -3 => value; -4 => key; -5 => table + if(lua_type(L, -1) != LUA_TTABLE) { + printf("Error in config: in group '%s': 'Entries' should be Table, is actually %s\n", group_name, lua_typename(L, lua_type(L, -1))); exit(1); } - entry_count = get_entry_count(L, entry_table_stack_index); + entry_count = get_entry_count(L); + // check that the group has at least 1 entry - if(entry_count <= 0) + if(entry_count <= 0) { printf("Skipping empty group '%s'\n", group_name); - + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + } else { (*g)[count] = create_group(group_name, entry_count); // sort the entries if necessary if(sort) { - sprintf(sort_cmd_lua, "table.sort(Groups[%d].Entries)", i); + sprintf(sort_cmd_lua, "table.sort(Groups[%d].Entries, function(a, b) return a.name < b.name end)", i); luaL_dostring(L, sort_cmd_lua); } // add entries to this group - add_entries(L, entry_table_stack_index, (*g)[count]); + add_entries(L, (*g)[count]); + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table // set the launcher, if applicable lua_pushstring(L, "Launcher"); - lua_gettable(L, group_table_stack_index); + // stack now contains: -1 => "Launcher"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => Launcher; -2 => key; -3 => value; -4 => key; -5 => table if(lua_type(L, -1) == LUA_TSTRING) { set_gprog((*g)[count], lua_tostring(L, -1)); } + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table // set the launcher flags, if applicable lua_pushstring(L, "Flags"); - lua_gettable(L, group_table_stack_index); + // stack now contains: -1 => "Flags"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => Flags; -2 => key; -3 => value; -4 => key; -5 => table if(lua_type(L, -1) == LUA_TSTRING) { set_gflags((*g)[count], lua_tostring(L, -1)); } + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table ++count; } } } + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table ++i; - } while(lua_type(L, group_table_stack_index) != LUA_TNIL); - - lua_pop(L, lua_gettop(L)-table_stack_index-1); + } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key + // but does not push anything.) + // Pop table + lua_pop(L, 1); + // Stack is now the same as it was on entry to this function } -void add_entries(lua_State *L, int table_stack_index, GROUP *g) { +void add_entries(lua_State *L, GROUP *g) { const char *entry_name; + const char *entry_path; + int entry_table_stack_index; int i = 1; // index in lua table int count = 0; // index in C struct - do { - lua_rawgeti(L, table_stack_index, i); - if(lua_type(L, -1) == LUA_TSTRING) { + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(lua_type(L, -1) == LUA_TNUMBER && lua_type(L, -2) == LUA_TTABLE) { + // check that the entry has a valid name + lua_pushstring(L, "name"); + // stack now contains: -1 => "name"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => name; -2 => key; -3 => value; -4 => key; -5 => table entry_name = lua_tostring(L, -1); + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + if(entry_name != NULL) { - set_gentry(g, count, create_entry(entry_name, entry_name, true)); + // get this entry's path, if applicable + lua_pushstring(L, "path"); + // stack now contains: -1 => "path"; -2 => key; -3 => value; -4 => key; -5 => table + lua_gettable(L, -3); + // stack now contains: -1 => path; -2 => key; -3 => value; -4 => key; -5 => table + if(lua_type(L, -1) == LUA_TSTRING) entry_path = lua_tostring(L, -1); + else entry_path = entry_name; + lua_pop(L, 1); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + + set_gentry(g, count, create_entry(entry_name, entry_path, true)); ++count; } } - ++i; - } while(lua_type(L, -1) != LUA_TNIL); - - lua_pop(L, lua_gettop(L)-table_stack_index-1); + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table + } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key } void stack_debug(lua_State *L) { @@ -279,6 +355,53 @@ void stack_debug(lua_State *L) { printf("DEBUGGING STACK:\n"); for(i = 1; i <= lua_gettop(L); ++i) { - printf("\t%d - %s\n", i, lua_typename(L, lua_type(L, i))); + printf("\t%d - %s", i, lua_typename(L, lua_type(L, i))); + + switch(lua_type(L, i)) { + case LUA_TSTRING: + printf(" - %s\n", lua_tostring(L, i)); + break; + + //case LUA_TTABLE: + // printf("\n"); + // table_debug(L, 2); + // break; + + default: + printf("\n"); + } + } +} + +// FIXME WIP debugging function +void table_debug(lua_State *L, int print_depth) { + int i; + + // stack now contains: -1 => table + lua_pushnil(L); + // stack now contains: -1 => nil; -2 => table + while (lua_next(L, -2)) { + // stack now contains: -1 => value; -2 => key; -3 => table + // copy the key so that lua_tostring does not modify the original + lua_pushvalue(L, -2); + // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table + const char *key = lua_tostring(L, -1); + const char *value = lua_typename(L, lua_type(L, -2)); + for(i = 0; i < print_depth; ++i) { + printf("\t"); + } + printf("%s => %s", key, value); + if(lua_type(L, -2) == LUA_TSTRING) { + printf(" - %s", lua_tostring(L, -2)); + } + printf("\n"); + // pop value + copy of key, leaving original key + lua_pop(L, 2); + // stack now contains: -1 => key; -2 => table } + // stack now contains: -1 => table (when lua_next returns 0 it pops the key + // but does not push anything.) + // Pop table + lua_pop(L, 1); + // Stack is now the same as it was on entry to this function } -- cgit