use fmt; use format::ini; use io; use os; use strings; // Configuration settings from the config file type config = struct { mods_dir: str, sets: []modset, }; type modset = (str, []modident); // Finds a given mod set. fn config_find_set(config: *config, set_name: str) (*modset | void) = { for (let set &.. config.sets) { if (set.0 == set_name) return set; }; }; // Frees resources related to a [[config]]. fn config_free(config: config) void = { free(config.mods_dir); for (let set &.. config.sets) { free(set.0); modident_free_all(set.1); }; free(config.sets); }; // Parses a configuration file entry and merges it into the config. fn config_handle_entry(config: *config, entry: ini::entry) void = { switch (entry.0) { case "sets" => let set: []modident = []; let mods = strings::split(entry.2, " ")!; for (let mod .. mods) append(set, modident_parse(mod))!; append(config.sets, (strings::dup(entry.1)!, set))!; case => switch (entry.1) { case "mods_dir" => free(config.mods_dir); config.mods_dir = strings::dup(entry.2)!; case => void; }; }; }; // Parses and returns configuration options from the config file. Defaults will // be provided if they are not specified or the config file does not exist. // The return value must be freed with [[config_free]]. fn config_parse(path: str) config = { const cwd = os::getcwd(); let config = config { mods_dir = strings::dup(cwd)!, sets = [] }; const config_file = os::open(path); if (config_file is io::file) { const config_file = config_file as io::file; defer io::close(config_file)!; let scanner = ini::scan(config_file); defer ini::finish(&scanner); for (let entry => ini::next(&scanner)!) { config_handle_entry(&config, entry); }; }; return config; };