summaryrefslogtreecommitdiff
path: root/hammer/runcommands.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/runcommands.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'hammer/runcommands.cpp')
-rw-r--r--hammer/runcommands.cpp418
1 files changed, 418 insertions, 0 deletions
diff --git a/hammer/runcommands.cpp b/hammer/runcommands.cpp
new file mode 100644
index 0000000..a67a0de
--- /dev/null
+++ b/hammer/runcommands.cpp
@@ -0,0 +1,418 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Handles running the OS commands for map compilation.
+//
+//=============================================================================
+
+#include "stdafx.h"
+#include <afxtempl.h>
+#include "GameConfig.h"
+#include "RunCommands.h"
+#include "Options.h"
+#include <process.h>
+#include "ProcessWnd.h"
+#include <io.h>
+#include <direct.h>
+#include "GlobalFunctions.h"
+#include "hammer.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+static bool s_bRunsCommands = false;
+
+bool IsRunningCommands() { return s_bRunsCommands; }
+
+static char *pszDocPath, *pszDocName, *pszDocExt;
+
+CProcessWnd procWnd;
+
+void FixGameVars(char *pszSrc, char *pszDst, BOOL bUseQuotes)
+{
+ // run through the parms list and substitute $variable strings for
+ // the real thing
+ char *pSrc = pszSrc, *pDst = pszDst;
+ BOOL bInQuote = FALSE;
+ while(pSrc[0])
+ {
+ if(pSrc[0] == '$') // found a parm
+ {
+ if(pSrc[1] == '$') // nope, it's a single symbol
+ {
+ *pDst++ = '$';
+ ++pSrc;
+ }
+ else
+ {
+ // figure out which parm it is ..
+ ++pSrc;
+
+ if (!bInQuote && bUseQuotes)
+ {
+ // not in quote, and subbing a variable.. start quote
+ *pDst++ = '\"';
+ bInQuote = TRUE;
+ }
+
+ if(!strnicmp(pSrc, "file", 4))
+ {
+ pSrc += 4;
+ strcpy(pDst, pszDocName);
+ pDst += strlen(pDst);
+ }
+ else if(!strnicmp(pSrc, "ext", 3))
+ {
+ pSrc += 3;
+ strcpy(pDst, pszDocExt);
+ pDst += strlen(pDst);
+ }
+ else if(!strnicmp(pSrc, "path", 4))
+ {
+ pSrc += 4;
+ strcpy(pDst, pszDocPath);
+ pDst += strlen(pDst);
+ }
+ else if(!strnicmp(pSrc, "exedir", 6))
+ {
+ pSrc += 6;
+ strcpy(pDst, g_pGameConfig->m_szGameExeDir);
+ pDst += strlen(pDst);
+ }
+ else if(!strnicmp(pSrc, "bspdir", 6))
+ {
+ pSrc += 6;
+ strcpy(pDst, g_pGameConfig->szBSPDir);
+ pDst += strlen(pDst);
+ }
+ else if(!strnicmp(pSrc, "bsp_exe", 7))
+ {
+ pSrc += 7;
+ strcpy(pDst, g_pGameConfig->szBSP);
+ pDst += strlen(pDst);
+ }
+ else if(!strnicmp(pSrc, "vis_exe", 7))
+ {
+ pSrc += 7;
+ strcpy(pDst, g_pGameConfig->szVIS);
+ pDst += strlen(pDst);
+ }
+ else if(!strnicmp(pSrc, "light_exe", 9))
+ {
+ pSrc += 9;
+ strcpy(pDst, g_pGameConfig->szLIGHT);
+ pDst += strlen(pDst);
+ }
+ else if(!strnicmp(pSrc, "game_exe", 8))
+ {
+ pSrc += 8;
+ strcpy(pDst, g_pGameConfig->szExecutable);
+ pDst += strlen(pDst);
+ }
+ else if (!strnicmp(pSrc, "gamedir", 7))
+ {
+ pSrc += 7;
+ strcpy(pDst, g_pGameConfig->m_szModDir);
+ pDst += strlen(pDst);
+ }
+ }
+ }
+ else
+ {
+ if(*pSrc == ' ' && bInQuote)
+ {
+ bInQuote = FALSE;
+ *pDst++ = '\"'; // close quotes
+ }
+
+ // just copy the char into the destination buffer
+ *pDst++ = *pSrc++;
+ }
+ }
+
+ if(bInQuote)
+ {
+ bInQuote = FALSE;
+ *pDst++ = '\"'; // close quotes
+ }
+
+ pDst[0] = 0;
+}
+
+static void RemoveQuotes(char *pBuf)
+{
+ if(pBuf[0] == '\"')
+ strcpy(pBuf, pBuf+1);
+ if(pBuf[strlen(pBuf)-1] == '\"')
+ pBuf[strlen(pBuf)-1] = 0;
+}
+
+LPCTSTR GetErrorString()
+{
+ static char szBuf[200];
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
+ szBuf, 200, NULL);
+ char *p = strchr(szBuf, '\r'); // get rid of \r\n
+ if(p) p[0] = 0;
+ return szBuf;
+}
+
+bool RunCommands(CCommandArray& Commands, LPCTSTR pszOrigDocName)
+{
+ s_bRunsCommands = true;
+
+ char szCurDir[MAX_PATH];
+ _getcwd(szCurDir, MAX_PATH);
+
+ procWnd.GetReady();
+
+ // cut up document name into file and extension components.
+ // create two sets of buffers - one set with the long filename
+ // and one set with the 8.3 format.
+
+ char szDocLongPath[MAX_PATH] = {0}, szDocLongName[MAX_PATH] = {0},
+ szDocLongExt[MAX_PATH] = {0};
+ char szDocShortPath[MAX_PATH] = {0}, szDocShortName[MAX_PATH] = {0},
+ szDocShortExt[MAX_PATH] = {0};
+
+ GetFullPathName(pszOrigDocName, MAX_PATH, szDocLongPath, NULL);
+ GetShortPathName(pszOrigDocName, szDocShortPath, MAX_PATH);
+
+ // split them up
+ char *p = strrchr(szDocLongPath, '.');
+ if(p && strrchr(szDocLongPath, '\\') < p && strrchr(szDocLongPath, '/') < p)
+ {
+ // got the extension
+ strcpy(szDocLongExt, p+1);
+ p[0] = 0;
+ }
+
+ p = strrchr(szDocLongPath, '\\');
+ if(!p)
+ p = strrchr(szDocLongPath, '/');
+ if(p)
+ {
+ // got the filepart
+ strcpy(szDocLongName, p+1);
+ p[0] = 0;
+ }
+
+ // split the short part up
+ p = strrchr(szDocShortPath, '.');
+ if(p && strrchr(szDocShortPath, '\\') < p && strrchr(szDocShortPath, '/') < p)
+ {
+ // got the extension
+ strcpy(szDocShortExt, p+1);
+ p[0] = 0;
+ }
+
+ p = strrchr(szDocShortPath, '\\');
+ if(!p)
+ p = strrchr(szDocShortPath, '/');
+ if(p)
+ {
+ // got the filepart
+ strcpy(szDocShortName, p+1);
+ p[0] = 0;
+ }
+
+ int iSize = Commands.GetSize(), i = 0;
+ char *ppParms[32];
+ while(iSize--)
+ {
+ CCOMMAND &cmd = Commands[i++];
+
+ // anything there?
+ if((!cmd.szRun[0] && !cmd.iSpecialCmd) || !cmd.bEnable)
+ continue;
+
+ // set name pointers for long filenames
+ pszDocExt = szDocLongExt;
+ pszDocName = szDocLongName;
+ pszDocPath = szDocLongPath;
+
+ char szNewParms[MAX_PATH*5], szNewRun[MAX_PATH*5];
+
+ // HACK: force the spawnv call for launching the game
+ if (!Q_stricmp(cmd.szRun, "$game_exe"))
+ {
+ cmd.bUseProcessWnd = FALSE;
+ }
+
+ FixGameVars(cmd.szRun, szNewRun, TRUE);
+ FixGameVars(cmd.szParms, szNewParms, TRUE);
+
+ CString strTmp;
+ strTmp.Format("\r\n"
+ "** Executing...\r\n"
+ "** Command: %s\r\n"
+ "** Parameters: %s\r\n\r\n", szNewRun, szNewParms);
+ procWnd.Append(strTmp);
+
+ // create a parameter list (not always required)
+ if(!cmd.bUseProcessWnd || cmd.iSpecialCmd)
+ {
+ p = szNewParms;
+ ppParms[0] = szNewRun;
+ int iArg = 1;
+ BOOL bDone = FALSE;
+ while(p[0])
+ {
+ ppParms[iArg++] = p;
+ while(p[0])
+ {
+ if(p[0] == ' ')
+ {
+ // found a space-separator
+ p[0] = 0;
+
+ p++;
+
+ // skip remaining white space
+ while (*p == ' ')
+ p++;
+
+ break;
+ }
+
+ // found the beginning of a quoted parameters
+ if(p[0] == '\"')
+ {
+ while(1)
+ {
+ p++;
+ if(p[0] == '\"')
+ {
+ // found the end
+ if(p[1] == 0)
+ bDone = TRUE;
+ p[1] = 0; // kick its ass
+ p += 2;
+
+ // skip remaining white space
+ while (*p == ' ')
+ p++;
+
+ break;
+ }
+ }
+ break;
+ }
+
+ // else advance p
+ ++p;
+ }
+
+ if(!p[0] || bDone)
+ break; // done.
+ }
+
+ ppParms[iArg] = NULL;
+
+ if(cmd.iSpecialCmd)
+ {
+ BOOL bError = FALSE;
+ LPCTSTR pszError = "";
+
+ if(cmd.iSpecialCmd == CCCopyFile && iArg == 3)
+ {
+ RemoveQuotes(ppParms[1]);
+ RemoveQuotes(ppParms[2]);
+
+ // don't copy if we're already there
+ if (stricmp(ppParms[1], ppParms[2]) &&
+ (!CopyFile(ppParms[1], ppParms[2], FALSE)))
+ {
+ bError = TRUE;
+ pszError = GetErrorString();
+ }
+ }
+ else if(cmd.iSpecialCmd == CCDelFile && iArg == 2)
+ {
+ RemoveQuotes(ppParms[1]);
+ if(!DeleteFile(ppParms[1]))
+ {
+ bError = TRUE;
+ pszError = GetErrorString();
+ }
+ }
+ else if(cmd.iSpecialCmd == CCRenameFile && iArg == 3)
+ {
+ RemoveQuotes(ppParms[1]);
+ RemoveQuotes(ppParms[2]);
+ if(rename(ppParms[1], ppParms[2]))
+ {
+ bError = TRUE;
+ pszError = strerror(errno);
+ }
+ }
+ else if(cmd.iSpecialCmd == CCChangeDir && iArg == 2)
+ {
+ RemoveQuotes(ppParms[1]);
+ if(mychdir(ppParms[1]) == -1)
+ {
+ bError = TRUE;
+ pszError = strerror(errno);
+ }
+ }
+
+ if(bError)
+ {
+ CString str;
+ str.Format("The command failed. Windows reported the error:\r\n"
+ " \"%s\"\r\n", pszError);
+ procWnd.Append(str);
+ procWnd.SetForegroundWindow();
+ str += "\r\nDo you want to continue?";
+ if(AfxMessageBox(str, MB_YESNO) == IDNO)
+ break;
+ }
+ }
+ else
+ {
+ // Change to the game exe folder before spawning the engine.
+ // This is necessary for Steam to find the correct Steam DLL (it
+ // uses the current working directory to search).
+ char szDir[MAX_PATH];
+ Q_strncpy(szDir, szNewRun, sizeof(szDir));
+ Q_StripFilename(szDir);
+
+ mychdir(szDir);
+
+ // YWB Force asynchronous operation so that engine doesn't hang on
+ // exit??? Seems to work.
+ // spawnv doesn't like quotes
+ RemoveQuotes(szNewRun);
+ _spawnv(/*cmd.bNoWait ?*/ _P_NOWAIT /*: P_WAIT*/, szNewRun,
+ (const char *const *)ppParms);
+ }
+ }
+ else
+ {
+ procWnd.Execute(szNewRun, szNewParms);
+ }
+
+ // check for existence?
+ if(cmd.bEnsureCheck)
+ {
+ char szFile[MAX_PATH];
+ FixGameVars(cmd.szEnsureFn, szFile, FALSE);
+ if(GetFileAttributes(szFile) == 0xFFFFFFFF)
+ {
+ // not there!
+ CString str;
+ str.Format("The file '%s' was not built.\n"
+ "Do you want to continue?", szFile);
+ procWnd.SetForegroundWindow();
+ if(AfxMessageBox(str, MB_YESNO) == IDNO)
+ break; // outta here
+ }
+ }
+ }
+
+ mychdir(szCurDir);
+
+ s_bRunsCommands = false;
+
+ return TRUE;
+}
+