diff --git a/source/common/searchpaths.cpp b/source/common/searchpaths.cpp index 5718f0c3b..d34d10a11 100644 --- a/source/common/searchpaths.cpp +++ b/source/common/searchpaths.cpp @@ -132,183 +132,17 @@ static void G_AddSteamPaths(TArray &searchpaths, const char *basepath) AddSearchPath(searchpaths, path); } -//------------------------------------------------------------------------- -// -// A bare-bones "parser" for Valve's KeyValues VDF format. -// There is no guarantee this will function properly with ill-formed files. -// -//------------------------------------------------------------------------- -static void KeyValues_SkipWhitespace(char **vdfbuf, char * const vdfbufend) +static TArray* g_searchpaths; + +static void AddAnItem(const char* item) { - while (((*vdfbuf)[0] == ' ' || (*vdfbuf)[0] == '\n' || (*vdfbuf)[0] == '\r' || (*vdfbuf)[0] == '\t' || (*vdfbuf)[0] == '\0') && *vdfbuf < vdfbufend) - (*vdfbuf)++; - - // comments - if ((*vdfbuf) + 2 < vdfbufend && (*vdfbuf)[0] == '/' && (*vdfbuf)[1] == '/') - { - while ((*vdfbuf)[0] != '\n' && (*vdfbuf)[0] != '\r' && *vdfbuf < vdfbufend) - (*vdfbuf)++; - - KeyValues_SkipWhitespace(vdfbuf, vdfbufend); - } -} -static void KeyValues_SkipToEndOfQuotedToken(char **vdfbuf, char * const vdfbufend) -{ - (*vdfbuf)++; - while ((*vdfbuf)[0] != '\"' && (*vdfbuf)[-1] != '\\' && *vdfbuf < vdfbufend) - (*vdfbuf)++; -} -static void KeyValues_SkipToEndOfUnquotedToken(char **vdfbuf, char * const vdfbufend) -{ - while ((*vdfbuf)[0] != ' ' && (*vdfbuf)[0] != '\n' && (*vdfbuf)[0] != '\r' && (*vdfbuf)[0] != '\t' && (*vdfbuf)[0] != '\0' && *vdfbuf < vdfbufend) - (*vdfbuf)++; -} -static void KeyValues_SkipNextWhatever(char **vdfbuf, char * const vdfbufend) -{ - KeyValues_SkipWhitespace(vdfbuf, vdfbufend); - - if (*vdfbuf == vdfbufend) - return; - - if ((*vdfbuf)[0] == '{') - { - (*vdfbuf)++; - do - { - KeyValues_SkipNextWhatever(vdfbuf, vdfbufend); - } - while ((*vdfbuf)[0] != '}'); - (*vdfbuf)++; - } - else if ((*vdfbuf)[0] == '\"') - KeyValues_SkipToEndOfQuotedToken(vdfbuf, vdfbufend); - else if ((*vdfbuf)[0] != '}') - KeyValues_SkipToEndOfUnquotedToken(vdfbuf, vdfbufend); - - KeyValues_SkipWhitespace(vdfbuf, vdfbufend); -} -static char* KeyValues_NormalizeToken(char **vdfbuf, char * const vdfbufend) -{ - char *token = *vdfbuf; - - if ((*vdfbuf)[0] == '\"' && *vdfbuf < vdfbufend) - { - token++; - - KeyValues_SkipToEndOfQuotedToken(vdfbuf, vdfbufend); - (*vdfbuf)[0] = '\0'; - - // account for escape sequences - char *writeseeker = token, *readseeker = token; - while (readseeker <= *vdfbuf) - { - if (readseeker[0] == '\\') - readseeker++; - - writeseeker[0] = readseeker[0]; - - writeseeker++; - readseeker++; - } - - return token; - } - - KeyValues_SkipToEndOfUnquotedToken(vdfbuf, vdfbufend); - (*vdfbuf)[0] = '\0'; - - return token; -} -static void KeyValues_FindKey(char **vdfbuf, char * const vdfbufend, const char *token) -{ - char *ParentKey = KeyValues_NormalizeToken(vdfbuf, vdfbufend); - if (token != NULL) // pass in NULL to find the next key instead of a specific one - while (Bstrcmp(ParentKey, token) != 0 && *vdfbuf < vdfbufend) - { - KeyValues_SkipNextWhatever(vdfbuf, vdfbufend); - ParentKey = KeyValues_NormalizeToken(vdfbuf, vdfbufend); - } - - KeyValues_SkipWhitespace(vdfbuf, vdfbufend); -} -static int32_t KeyValues_FindParentKey(char **vdfbuf, char * const vdfbufend, const char *token) -{ - KeyValues_SkipWhitespace(vdfbuf, vdfbufend); - - // end of scope - if ((*vdfbuf)[0] == '}') - return 0; - - KeyValues_FindKey(vdfbuf, vdfbufend, token); - - // ignore the wrong type - while ((*vdfbuf)[0] != '{' && *vdfbuf < vdfbufend) - { - KeyValues_SkipNextWhatever(vdfbuf, vdfbufend); - KeyValues_FindKey(vdfbuf, vdfbufend, token); - } - - if (*vdfbuf == vdfbufend) - return 0; - - return 1; -} -static char* KeyValues_FindKeyValue(char **vdfbuf, char * const vdfbufend, const char *token) -{ - KeyValues_SkipWhitespace(vdfbuf, vdfbufend); - - // end of scope - if ((*vdfbuf)[0] == '}') - return NULL; - - KeyValues_FindKey(vdfbuf, vdfbufend, token); - - // ignore the wrong type - while ((*vdfbuf)[0] == '{' && *vdfbuf < vdfbufend) - { - KeyValues_SkipNextWhatever(vdfbuf, vdfbufend); - KeyValues_FindKey(vdfbuf, vdfbufend, token); - } - - KeyValues_SkipWhitespace(vdfbuf, vdfbufend); - - if (*vdfbuf == vdfbufend) - return NULL; - - return KeyValues_NormalizeToken(vdfbuf, vdfbufend); + AddSearchPath(*g_searchpaths, item); } -//------------------------------------------------------------------------- -// -// -// -//------------------------------------------------------------------------- - -static void G_ParseSteamKeyValuesForPaths(TArray &searchpaths, const char *vdf) -{ - FileReader fr; - if (fr.Open(vdf)) - { - auto data = fr.Read(); - if (data.Size() == 0) return; - } - - auto vdfvuf = (char*)data.Data(); - auto vdfbufend = vdfbuf + data.Size(); - - if (KeyValues_FindParentKey(&vdfbuf, vdfbufend, "LibraryFolders")) - { - char *result; - vdfbuf++; - while ((result = KeyValues_FindKeyValue(&vdfbuf, vdfbufend, NULL)) != NULL) - G_AddSteamPaths(searchpaths, result); - } -} -#endif -#if defined (__FreeBSD__) || defined(__OpenBSD__) || defined (__linux__) +#ifndef __APPLE__ //------------------------------------------------------------------------- // @@ -325,17 +159,17 @@ void G_AddExternalSearchPaths(TArray &searchpaths) G_AddSteamPaths(searchpaths, buf); path.Format("%s/.steam/steam/steamapps/libraryfolders.vdf", homepath); - G_ParseSteamKeyValuesForPaths(searchpaths, buf); + g_searchpaths = &searchpaths; + G_ParseSteamKeyValuesForPaths(searchpaths, buf, AddAnItem); } -#elif defined __APPLE__ +#else //------------------------------------------------------------------------- // // // //------------------------------------------------------------------------- - void G_AddExternalSearchPaths(TArray &searchpaths) { char *applications[] = { osx_getapplicationsdir(0), osx_getapplicationsdir(1) }; @@ -346,13 +180,14 @@ void G_AddExternalSearchPaths(TArray &searchpaths) char buf[BMAX_PATH]; int32_t i; + g_searchpaths = &searchpaths; for (i = 0; i < 2; i++) { path.Format("%s/Steam", support[i]); G_AddSteamPaths(searchpaths, buf); path.Format("%s/Steam/steamapps/libraryfolders.vdf", support[i]); - G_ParseSteamKeyValuesForPaths(searchpaths, buf); + G_ParseSteamKeyValuesForPaths(searchpaths, buf, AddAnItem); // Duke Nukem 3D: Atomic Edition (GOG.com) path.Format("%s/Duke Nukem 3D.app/Contents/Resources/Duke Nukem 3D.boxer/C.harddisk", applications[i]);