/* SAction::initActions * Loads and parses all SActions configured in actions.cfg in the * program resource archive *******************************************************************/ bool SAction::initActions() { // Get actions.cfg from slade.pk3 auto cfg_entry = theArchiveManager->programResourceArchive()->entryAtPath("actions.cfg"); if (!cfg_entry) return false; Parser parser(cfg_entry->getParentDir()); if (parser.parseText(cfg_entry->getMCData(), "actions.cfg")) { auto root = parser.parseTreeRoot(); for (unsigned a = 0; a < root->nChildren(); a++) { auto node = root->getChildPTN(a); // Single action if (S_CMPNOCASE(node->type(), "action")) { auto action = new SAction(node->getName(), node->getName()); if (action->parse(node)) actions.push_back(action); else delete action; } // Group of actions else if (S_CMPNOCASE(node->getName(), "group")) { int group = newGroup(); for (unsigned b = 0; b < node->nChildren(); b++) { auto group_node = node->getChildPTN(b); if (S_CMPNOCASE(group_node->type(), "action")) { auto action = new SAction(group_node->getName(), group_node->getName()); if (action->parse(group_node)) { action->group = group; actions.push_back(action); } else delete action; } } } } } return true; }
/* Executables::parse * Parses an executables configuration from [p] *******************************************************************/ void Executables::parse(Parser* p, bool custom) { auto n = p->parseTreeRoot()->getChildPTN("executables"); if (!n) return; for (unsigned a = 0; a < n->nChildren(); a++) { auto exe_node = n->getChildPTN(a); string type = exe_node->type(); // Game Executable (if type is blank it's a game executable in old config format) if (type == "game_exe" || type.IsEmpty()) parseGameExe(exe_node, custom); // External Executable else if (type == "external_exe") parseExternalExe(exe_node); } }
/* EntryDataFormat::readDataFormatDefinition * Parses a user data format definition (unimplemented, currently) *******************************************************************/ bool EntryDataFormat::readDataFormatDefinition(MemChunk& mc) { // Parse the definition Parser p; p.parseText(mc); // Get data_formats tree auto pt_formats = p.parseTreeRoot()->getChildPTN("data_formats"); // Check it exists if (!pt_formats) return false; // Go through all parsed types for (unsigned a = 0; a < pt_formats->nChildren(); a++) { // Get child as ParseTreeNode auto formatnode = pt_formats->getChildPTN(a); // Create+add new data format EntryDataFormat* edf = new EntryDataFormat(formatnode->getName().Lower()); /* // Copy from existing type if inherited if (!formatnode->getInherit().IsEmpty()) { EntryType* parent_type = EntryType::getType(formatnode->getInherit()); if (parent_type != EntryType::unknownType()) parent_type->copyToType(ntype); else LOG_MESSAGE(1, "Warning: Entry type %s inherits from unknown type %s", ntype->getId(), typenode->getInherit()); } */ } return true; }
// ---------------------------------------------------------------------------- // TextLanguage::readLanguageDefinition // // Reads in a text definition of a language. See slade.pk3 for // formatting examples // ---------------------------------------------------------------------------- bool TextLanguage::readLanguageDefinition(MemChunk& mc, string source) { Tokenizer tz; // Open the given text data if (!tz.openMem(mc, source)) { Log::warning(1, S_FMT("Warning: Unable to open %s", source)); return false; } // Parse the definition text ParseTreeNode root; if (!root.parse(tz)) return false; // Get parsed data for (unsigned a = 0; a < root.nChildren(); a++) { auto node = root.getChildPTN(a); // Create language TextLanguage* lang = new TextLanguage(node->getName()); // Check for inheritance if (!node->inherit().IsEmpty()) { TextLanguage* inherit = fromId(node->inherit()); if (inherit) inherit->copyTo(lang); else Log::warning( 1, S_FMT("Warning: Language %s inherits from undefined language %s", node->getName(), node->inherit()) ); } // Parse language info for (unsigned c = 0; c < node->nChildren(); c++) { auto child = node->getChildPTN(c); // Language name if (S_CMPNOCASE(child->getName(), "name")) lang->setName(child->stringValue()); // Comment begin else if (S_CMPNOCASE(child->getName(), "comment_begin")) { lang->setCommentBeginList(child->stringValues()); } // Comment end else if (S_CMPNOCASE(child->getName(), "comment_end")) { lang->setCommentEndList(child->stringValues()); } // Line comment else if (S_CMPNOCASE(child->getName(), "comment_line")) { lang->setLineCommentList(child->stringValues()); } // Preprocessor else if (S_CMPNOCASE(child->getName(), "preprocessor")) lang->setPreprocessor(child->stringValue()); // Case sensitive else if (S_CMPNOCASE(child->getName(), "case_sensitive")) lang->setCaseSensitive(child->boolValue()); // Doc comment else if (S_CMPNOCASE(child->getName(), "comment_doc")) lang->setDocComment(child->stringValue()); // Keyword lookup link else if (S_CMPNOCASE(child->getName(), "keyword_link")) lang->word_lists_[WordType::Keyword].lookup_url = child->stringValue(); // Constant lookup link else if (S_CMPNOCASE(child->getName(), "constant_link")) lang->word_lists_[WordType::Constant].lookup_url = child->stringValue(); // Function lookup link else if (S_CMPNOCASE(child->getName(), "function_link")) lang->f_lookup_url_ = child->stringValue(); // Jump blocks else if (S_CMPNOCASE(child->getName(), "blocks")) { for (unsigned v = 0; v < child->nValues(); v++) lang->jump_blocks_.push_back(child->stringValue(v)); } else if (S_CMPNOCASE(child->getName(), "blocks_ignore")) { for (unsigned v = 0; v < child->nValues(); v++) lang->jb_ignore_.push_back(child->stringValue(v)); } // Block begin else if (S_CMPNOCASE(child->getName(), "block_begin")) lang->block_begin_ = child->stringValue(); // Block end else if (S_CMPNOCASE(child->getName(), "block_end")) lang->block_end_ = child->stringValue(); // Preprocessor block begin else if (S_CMPNOCASE(child->getName(), "pp_block_begin")) { for (unsigned v = 0; v < child->nValues(); v++) lang->pp_block_begin_.push_back(child->stringValue(v)); } // Preprocessor block end else if (S_CMPNOCASE(child->getName(), "pp_block_end")) { for (unsigned v = 0; v < child->nValues(); v++) lang->pp_block_end_.push_back(child->stringValue(v)); } // Word block begin else if (S_CMPNOCASE(child->getName(), "word_block_begin")) { for (unsigned v = 0; v < child->nValues(); v++) lang->word_block_begin_.push_back(child->stringValue(v)); } // Word block end else if (S_CMPNOCASE(child->getName(), "word_block_end")) { for (unsigned v = 0; v < child->nValues(); v++) lang->word_block_end_.push_back(child->stringValue(v)); } // Keywords else if (S_CMPNOCASE(child->getName(), "keywords")) { // Go through values for (unsigned v = 0; v < child->nValues(); v++) { string val = child->stringValue(v); // Check for '$override' if (S_CMPNOCASE(val, "$override")) { // Clear any inherited keywords lang->clearWordList(WordType::Keyword); } // Not a special symbol, add as keyword else lang->addWord(WordType::Keyword, val); } } // Constants else if (S_CMPNOCASE(child->getName(), "constants")) { // Go through values for (unsigned v = 0; v < child->nValues(); v++) { string val = child->stringValue(v); // Check for '$override' if (S_CMPNOCASE(val, "$override")) { // Clear any inherited constants lang->clearWordList(WordType::Constant); } // Not a special symbol, add as constant else lang->addWord(WordType::Constant, val); } } // Types else if (S_CMPNOCASE(child->getName(), "types")) { // Go through values for (unsigned v = 0; v < child->nValues(); v++) { string val = child->stringValue(v); // Check for '$override' if (S_CMPNOCASE(val, "$override")) { // Clear any inherited constants lang->clearWordList(WordType::Type); } // Not a special symbol, add as constant else lang->addWord(WordType::Type, val); } } // Properties else if (S_CMPNOCASE(child->getName(), "properties")) { // Go through values for (unsigned v = 0; v < child->nValues(); v++) { string val = child->stringValue(v); // Check for '$override' if (S_CMPNOCASE(val, "$override")) { // Clear any inherited constants lang->clearWordList(WordType::Property); } // Not a special symbol, add as constant else lang->addWord(WordType::Property, val); } } // Functions else if (S_CMPNOCASE(child->getName(), "functions")) { bool lang_has_void = lang->isWord(Keyword, "void") || lang->isWord(Type, "void"); if (lang->id_ != "zscript") { // Go through children (functions) for (unsigned f = 0; f < child->nChildren(); f++) { auto child_func = child->getChildPTN(f); string params; // Simple definition if (child_func->nChildren() == 0) { if (child_func->stringValue(0).empty()) { if (lang_has_void) params = "void"; else params = ""; } else { params = child_func->stringValue(0); } // Add function lang->addFunction( child_func->getName(), params, "", "", !child_func->getName().Contains("."), child_func->type()); // Add args for (unsigned v = 1; v < child_func->nValues(); v++) lang->addFunction(child_func->getName(), child_func->stringValue(v)); } // Full definition else { string name = child_func->getName(); vector<string> args; string desc = ""; string deprecated = ""; for (unsigned p = 0; p < child_func->nChildren(); p++) { auto child_prop = child_func->getChildPTN(p); if (child_prop->getName() == "args") { for (unsigned v = 0; v < child_prop->nValues(); v++) args.push_back(child_prop->stringValue(v)); } else if (child_prop->getName() == "description") desc = child_prop->stringValue(); else if (child_prop->getName() == "deprecated") deprecated = child_prop->stringValue(); } if (args.empty() && lang_has_void) args.push_back("void"); for (unsigned as = 0; as < args.size(); as++) lang->addFunction(name, args[as], desc, deprecated, as == 0, child_func->type()); } } } // ZScript function info which cannot be parsed from (g)zdoom.pk3 else { zfunc_ex_prop ex_prop; for (unsigned f = 0; f < child->nChildren(); f++) { auto child_func = child->getChildPTN(f); for (unsigned p = 0; p < child_func->nChildren(); ++p) { auto child_prop = child_func->getChildPTN(p); if (child_prop->getName() == "description") ex_prop.description = child_prop->stringValue(); else if (child_prop->getName() == "deprecated_f") ex_prop.deprecated_f = child_prop->stringValue(); } lang->zfuncs_ex_props_.emplace(child_func->getName(), ex_prop); } } } } } return true; }
// ----------------------------------------------------------------------------- // Automatically seek IWADs to populate the list // ----------------------------------------------------------------------------- void BaseResourceArchivesPanel::autodetect() { // List of known IWADs and common aliases ArchiveEntry* iwadlist = App::archiveManager().programResourceArchive()->entryAtPath("config/iwads.cfg"); if (!iwadlist) return; Parser p; p.parseText(iwadlist->getMCData(), "slade.pk3:config/iwads.cfg"); // Find IWADs from DOOMWADDIR and DOOMWADPATH // See http://doomwiki.org/wiki/Environment_variables string doomwaddir, doomwadpath, envvar; envvar = "DOOMWADDIR"; wxGetEnv(envvar, &doomwaddir); envvar = "DOOMWADPATH"; wxGetEnv(envvar, &doomwadpath); if (doomwaddir.length() || doomwadpath.length()) { #ifdef WIN32 char separator = ';'; doomwadpath.Replace("\\", "/", true); doomwaddir.Replace("\\", "/", true); #else char separator = ':'; #endif wxArrayString paths = wxSplit(doomwadpath, separator); paths.Add(doomwaddir); wxArrayString iwadnames; auto list = p.parseTreeRoot()->getChildPTN("iwads"); for (size_t i = 0; i < list->nChildren(); ++i) iwadnames.Add(list->getChild(i)->getName()); // Look for every known IWAD in every known IWAD directory for (size_t i = 0; i < paths.size(); ++i) { string folder = paths[i]; if (folder.Last() != '/') folder += '/'; for (size_t j = 0; j < iwadnames.size(); ++j) { string iwad = folder + iwadnames[j]; #ifndef WIN32 // Try a couple variants before throwing the towel about a name if (!wxFileExists(iwad)) iwad = folder + iwadnames[j].Capitalize(); if (!wxFileExists(iwad)) iwad = folder + iwadnames[j].Upper(); #endif // If a valid combo is found, add it to the list unless already present if (wxFileExists(iwad)) { // Verify existence before adding it to the list if (list_base_archive_paths_->FindString(iwad) == wxNOT_FOUND) { App::archiveManager().addBaseResourcePath(iwad); list_base_archive_paths_->Append(iwad); } } } } } // Let's take a look at the registry wxArrayString paths; string path; string gamepath; // Now query GOG.com paths -- Windows only for now #ifdef __WXMSW__ #ifdef _WIN64 string gogregistrypath = "Software\\Wow6432Node\\GOG.com"; #else // If a 32-bit ZDoom runs on a 64-bit Windows, this will be transparently and // automatically redirected to the Wow6432Node address instead, so this address // should be safe to use in all cases. string gogregistrypath = "Software\\GOG.com"; #endif if (QueryPathKey(wxRegKey::HKLM, gogregistrypath, "DefaultPackPath", path)) { auto list = p.parseTreeRoot()->getChildPTN("gog"); for (size_t i = 0; i < list->nChildren(); ++i) { auto child = list->getChildPTN(i); gamepath = gogregistrypath + (child->getChildPTN("id"))->stringValue(); if (QueryPathKey(wxRegKey::HKLM, gamepath, "Path", path)) paths.Add(path + (child->getChildPTN("path"))->stringValue()); } } #endif // Now query Steam paths -- Windows only for now as well #ifdef __WXMSW__ if (QueryPathKey(wxRegKey::HKCU, "Software\\Valve\\Steam", "SteamPath", gamepath) || QueryPathKey(wxRegKey::HKLM, "Software\\Valve\\Steam", "InstallPath", gamepath)) { gamepath += "/SteamApps/common/"; auto list = p.parseTreeRoot()->getChildPTN("steam"); for (size_t i = 0; i < list->nChildren(); ++i) paths.Add(gamepath + (list->getChildPTN(i))->stringValue()); } #else // TODO: Querying Steam registry on Linux and OSX. This involves parsing Steam's config.vdf file, which is found in // FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &folder) + "/Steam/config/config.vdf" on // OSX and in ~home/.local/share/Steam/config/config.vdf on Linux/BSD systems. There's also default install dirs in // appSupportPath + "/Steam/SteamApps/common" for OSX, ~home/.local/share/Steam/SteamApps/common for Linux/BSD. #endif // Add GOG & Steam paths for (size_t i = 0; i < paths.size(); ++i) { string iwad = paths[i]; iwad.Replace("\\", "/", true); if (wxFileExists(iwad)) { // Verify existence before adding it to the list if (list_base_archive_paths_->FindString(iwad) == wxNOT_FOUND) { App::archiveManager().addBaseResourcePath(iwad); list_base_archive_paths_->Append(iwad); } } } }