#include "precompiled.h" class CCommandLine: public ICommandLine { public: CCommandLine(); virtual ~CCommandLine(); void CreateCmdLine(const char *commandline); void CreateCmdLine(int argc, const char *argv[]); const char *GetCmdLine() const; // Check whether a particular parameter exists const char *CheckParm(const char *psz, char **ppszValue = nullptr) const; void RemoveParm(const char *pszParm); void AppendParm(const char *pszParm, const char *pszValues); void SetParm(const char *pszParm, const char *pszValues); void SetParm(const char *pszParm, int iValue); // When the commandline contains @name, it reads the parameters from that file void LoadParametersFromFile(const char *&pSrc, char *&pDst, int maxDestLen); private: // Copy of actual command line char *m_pszCmdLine; }; CCommandLine g_CmdLine; ICommandLine *cmdline = &g_CmdLine; ICommandLine *CommandLine() { return &g_CmdLine; } CCommandLine::CCommandLine() { m_pszCmdLine = nullptr; } CCommandLine::~CCommandLine() { if (m_pszCmdLine) { delete [] m_pszCmdLine; m_pszCmdLine = nullptr; } } char *CopyString(const char *src) { if (!src) return nullptr; char *out = (char *)new char[strlen(src) + 1]; strcpy(out, src); return out; } // Creates a command line from the arguments passed in void CCommandLine::CreateCmdLine(int argc, const char *argv[]) { char cmdline[4096] = ""; const int MAX_CHARS = sizeof(cmdline) - 1; for (int i = 0; i < argc; ++i) { if (strchr(argv[i], ' ')) { strncat(cmdline, "\"", MAX_CHARS); strncat(cmdline, argv[i], MAX_CHARS); strncat(cmdline, "\"", MAX_CHARS); } else { strncat(cmdline, argv[i], MAX_CHARS); } strncat(cmdline, " ", MAX_CHARS); } cmdline[strlen(cmdline)] = '\0'; CreateCmdLine(cmdline); } void CCommandLine::LoadParametersFromFile(const char *&pSrc, char *&pDst, int maxDestLen) { // Suck out the file name char szFileName[ MAX_PATH ]; char *pOut; char *pDestStart = pDst; // Skip the @ sign pSrc++; pOut = szFileName; while (*pSrc && *pSrc != ' ') { *pOut++ = *pSrc++; #if 0 if ((pOut - szFileName) >= (MAX_PATH - 1)) break; #endif } *pOut = '\0'; // Skip the space after the file name if (*pSrc) pSrc++; // Now read in parameters from file FILE *fp = fopen(szFileName, "r"); if (fp) { char c; c = (char)fgetc(fp); while (c != EOF) { // Turn return characters into spaces if (c == '\n') c = ' '; *pDst++ = c; #if 0 // Don't go past the end, and allow for our terminating space character AND a terminating null character. if ((pDst - pDestStart) >= (maxDestLen - 2)) break; #endif // Get the next character, if there are more c = (char)fgetc(fp); } // Add a terminating space character *pDst++ = ' '; fclose(fp); } else { printf("Parameter file '%s' not found, skipping...", szFileName); } } // Purpose: Create a command line from the passed in string // Note that if you pass in a @filename, then the routine will read settings from a file instead of the command line void CCommandLine::CreateCmdLine(const char *commandline) { if (m_pszCmdLine) { delete[] m_pszCmdLine; m_pszCmdLine = nullptr; } char szFull[4096]; char *pDst = szFull; const char *pSrc = commandline; bool allowAtSign = true; while (*pSrc) { if (*pSrc == '@') { if (allowAtSign) { LoadParametersFromFile(pSrc, pDst, sizeof(szFull) - (pDst - szFull)); continue; } } allowAtSign = isspace(*pSrc) != 0; #if 0 // Don't go past the end. if ((pDst - szFull) >= (sizeof(szFull) - 1)) break; #endif *pDst++ = *pSrc++; } *pDst = '\0'; int len = strlen(szFull) + 1; m_pszCmdLine = new char[len]; memcpy(m_pszCmdLine, szFull, len); } // Purpose: Remove specified string ( and any args attached to it ) from command line void CCommandLine::RemoveParm(const char *pszParm) { if (!m_pszCmdLine) return; if (!pszParm || *pszParm == '\0') return; // Search for first occurrence of pszParm char *p, *found; char *pnextparam; int n; int curlen; p = m_pszCmdLine; while (*p) { curlen = strlen(p); found = strstr(p, pszParm); if (!found) break; pnextparam = found + 1; while (pnextparam && *pnextparam && (*pnextparam != '-') && (*pnextparam != '+')) pnextparam++; if (pnextparam && *pnextparam) { // We are either at the end of the string, or at the next param. Just chop out the current param. // # of characters after this param. n = curlen - (pnextparam - p); memcpy(found, pnextparam, n); found[n] = '\0'; } else { // Clear out rest of string. n = pnextparam - found; memset(found, 0, n); } } // Strip and trailing ' ' characters left over. while (1) { int curpos = strlen(m_pszCmdLine); if (curpos == 0 || m_pszCmdLine[ curpos - 1 ] != ' ') break; m_pszCmdLine[curpos - 1] = '\0'; } } // Purpose: Append parameter and argument values to command line void CCommandLine::AppendParm(const char *pszParm, const char *pszValues) { int nNewLength = 0; char *pCmdString; // Parameter. nNewLength = strlen(pszParm); // Values + leading space character. if (pszValues) nNewLength += strlen(pszValues) + 1; // Terminal 0; nNewLength++; if (!m_pszCmdLine) { m_pszCmdLine = new char[ nNewLength ]; strcpy(m_pszCmdLine, pszParm); if (pszValues) { strcat(m_pszCmdLine, " "); strcat(m_pszCmdLine, pszValues); } return; } // Remove any remnants from the current Cmd Line. RemoveParm(pszParm); nNewLength += strlen(m_pszCmdLine) + 1 + 1; pCmdString = new char[ nNewLength ]; memset(pCmdString, 0, nNewLength); strcpy(pCmdString, m_pszCmdLine); // Copy old command line. strcat(pCmdString, " "); // Put in a space strcat(pCmdString, pszParm); if (pszValues) { strcat(pCmdString, " "); strcat(pCmdString, pszValues); } // Kill off the old one delete[] m_pszCmdLine; // Point at the new command line. m_pszCmdLine = pCmdString; } void CCommandLine::SetParm(const char *pszParm, const char *pszValues) { RemoveParm(pszParm); AppendParm(pszParm, pszValues); } void CCommandLine::SetParm(const char *pszParm, int iValue) { char buf[64]; _snprintf(buf, sizeof(buf), "%d", iValue); SetParm(pszParm, buf); } // Purpose: Search for the parameter in the current commandline const char *CCommandLine::CheckParm(const char *psz, char **ppszValue) const { static char sz[128] = ""; if (!m_pszCmdLine) return nullptr; char *pret = strstr(m_pszCmdLine, psz); if (!pret || !ppszValue) return pret; *ppszValue = nullptr; // find the next whitespace char *p1 = pret; do { ++p1; } while (*p1 != ' ' && *p1); int i = 0; char *p2 = p1 + 1; do { if (p2[i] == '\0' || p2[i] == ' ') break; sz[i++] = p2[i]; } while (i < sizeof(sz)); sz[i] = '\0'; *ppszValue = sz; return pret; } const char *CCommandLine::GetCmdLine() const { return m_pszCmdLine; }