raze-gles/source/build/src/common.cpp
2019-12-19 20:04:17 +01:00

300 lines
7.7 KiB
C++

#include "compat.h"
#include "build.h"
#include "scriptfile.h"
#include "baselayer.h"
#include "common.h"
#include "../../glbackend/glbackend.h"
// def/clipmap handling
#ifdef HAVE_CLIPSHAPE_FEATURE
GrowArray<char *> g_clipMapFiles;
#endif
void SetClipshapes()
{
#ifdef HAVE_CLIPSHAPE_FEATURE
// pre-form the default 10 clipmaps
for (int j = '0'; j <= '9'; ++j)
{
char clipshape[16] = "_clipshape0.map";
clipshape[10] = j;
g_clipMapFiles.append(Xstrdup(clipshape));
}
#endif
}
#ifdef HAVE_CLIPSHAPE_FEATURE
void G_AddClipMap(const char *buffer)
{
g_clipMapFiles.append(Xstrdup(buffer));
}
#endif
//////////
int32_t getatoken(scriptfile *sf, const tokenlist *tl, int32_t ntokens)
{
char *tok;
int32_t i;
if (!sf) return T_ERROR;
tok = scriptfile_gettoken(sf);
if (!tok) return T_EOF;
for (i=ntokens-1; i>=0; i--)
{
if (!Bstrcasecmp(tok, tl[i].text))
return tl[i].tokenid;
}
return T_ERROR;
}
//////////
// Copy FN to WBUF and append an extension if it's not there, which is checked
// case-insensitively.
// Returns: 1 if not all characters could be written to WBUF, 0 else.
int32_t maybe_append_ext(char *wbuf, int32_t wbufsiz, const char *fn, const char *ext)
{
const int32_t slen=Bstrlen(fn), extslen=Bstrlen(ext);
const int32_t haveext = (slen>=extslen && Bstrcasecmp(&fn[slen-extslen], ext)==0);
Bassert((intptr_t)wbuf != (intptr_t)fn); // no aliasing
// If 'fn' has no extension suffixed, append one.
return (Bsnprintf(wbuf, wbufsiz, "%s%s", fn, haveext ? "" : ext) >= wbufsiz);
}
int32_t ldist(const void *s1, const void *s2)
{
auto sp1 = (vec2_t const *)s1;
auto sp2 = (vec2_t const *)s2;
return sepldist(sp1->x - sp2->x, sp1->y - sp2->y)
+ (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 1 : 0);
}
int32_t dist(const void *s1, const void *s2)
{
auto sp1 = (vec3_t const *)s1;
auto sp2 = (vec3_t const *)s2;
return sepdist(sp1->x - sp2->x, sp1->y - sp2->y, sp1->z - sp2->z);
}
int32_t FindDistance2D(int32_t x, int32_t y)
{
return sepldist(x, y);
}
int32_t FindDistance3D(int32_t x, int32_t y, int32_t z)
{
return sepdist(x, y, z);
}
#if defined _WIN32 && !defined EDUKE32_STANDALONE
# define NEED_SHLWAPI_H
# include "windows_inc.h"
# ifndef KEY_WOW64_64KEY
# define KEY_WOW64_64KEY 0x0100
# endif
# ifndef KEY_WOW64_32KEY
# define KEY_WOW64_32KEY 0x0200
# endif
int Paths_ReadRegistryValue(char const * const SubKey, char const * const Value, char * const Output, DWORD * OutputSize)
{
// KEY_WOW64_32KEY gets us around Wow6432Node on 64-bit builds
REGSAM const wow64keys[] = { KEY_WOW64_32KEY, KEY_WOW64_64KEY };
for (auto &wow64key : wow64keys)
{
HKEY hkey;
LONG keygood = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NULL, 0, KEY_READ | wow64key, &hkey);
if (keygood != ERROR_SUCCESS)
continue;
LONG retval = SHGetValueA(hkey, SubKey, Value, NULL, Output, OutputSize);
RegCloseKey(hkey);
if (retval == ERROR_SUCCESS)
return 1;
}
return 0;
}
#endif
// 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)
{
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);
}
void Paths_ParseSteamKeyValuesForPaths(const char *vdf, SteamPathParseFunc func)
{
FileReader fr;
if (!fr.OpenFile(vdf)) return;
auto size = fr.GetLength();
char *vdfbuf, *vdfbufend;
if (size == 0)
return;
auto vdfbuffer = fr.ReadPadded(1);
vdfbuf = (char*)vdfbuffer.Data();
vdfbufend = vdfbuf + size;
if (KeyValues_FindParentKey(&vdfbuf, vdfbufend, "LibraryFolders"))
{
char *result;
vdfbuf++;
while ((result = KeyValues_FindKeyValue(&vdfbuf, vdfbufend, NULL)) != NULL)
func(result);
}
}