//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1996 - 1999 // // File: cwargv.cpp // // Contents: argv parsing api // // History: 02-Oct-1997 pberkman create // //-------------------------------------------------------------------------- #include "global.hxx" #include "cwargv.hxx" #include "fparse.hxx" #define SID_FILES 0 typedef struct ARGVSTORAGE_ { DWORD dwsidOption; WCHAR *pwszOption; DWORD dwsidOptionHelp; WCHAR *pwszOptionHelp; BOOL fHiddenCmd; BOOL fSet; DWORD dwValueType; union { WCHAR *pwszValue; WCHAR *pwszCmdFile; DWORD dwValue; BOOL fValue; }; } ARGVSTORAGE; cWArgv_::cWArgv_(HINSTANCE hInst0, BOOL *pfFailed, BOOL fChkCmdFile) { pwszThisFilename = NULL; // don't delete! pwszUsageWord = NULL; pwszUsageOptionsText = NULL; pwszUsageCmdFileText = NULL; pwszUsageAddText = NULL; pwszOptionParamText = NULL; pwszUsageString = NULL; pwszNonParamArgBlanks = NULL; fShowHiddenArgs = FALSE; fNonHiddenParamArgs = FALSE; dwLongestArg = 0; this->hInst = hInst0; this->fChkCmdF = fChkCmdFile; pArgs = new Stack_(NULL); // no sorting! if (pArgs == NULL) { *pfFailed = TRUE; } else { *pfFailed = FALSE; } } cWArgv_::~cWArgv_(void) { ARGVSTORAGE *pArg; DWORD dwIdx; DELETE_OBJECT(pwszUsageWord); DELETE_OBJECT(pwszUsageOptionsText); DELETE_OBJECT(pwszUsageCmdFileText); DELETE_OBJECT(pwszUsageAddText); DELETE_OBJECT(pwszOptionParamText); DELETE_OBJECT(pwszUsageString); DELETE_OBJECT(pwszNonParamArgBlanks); dwIdx = 0; while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx)) { DELETE_OBJECT(pArg->pwszOption); DELETE_OBJECT(pArg->pwszOptionHelp); dwIdx++; } DELETE_OBJECT(pArgs); } void cWArgv_::AddUsageText(DWORD dwsidUsageWord, DWORD dwsidUsageOptions, DWORD dwsidUsageCmdFileText, DWORD dwsidUsageAddText, DWORD dwsidOptionParamText) { WCHAR wszString[MAX_PATH]; wszString[0] = NULL; LoadStringU(this->hInst, dwsidUsageWord, &wszString[0], MAX_PATH); if (wszString[0]) { if (!(pwszUsageWord = new WCHAR[wcslen(&wszString[0]) + 1])) { return; } wcscpy(pwszUsageWord, &wszString[0]); } wszString[0] = NULL; LoadStringU(this->hInst, dwsidUsageOptions, &wszString[0], MAX_PATH); if (wszString[0]) { if (!(pwszUsageOptionsText = new WCHAR[wcslen(&wszString[0]) + 1])) { return; } wcscpy(pwszUsageOptionsText, &wszString[0]); } wszString[0] = NULL; LoadStringU(this->hInst, dwsidUsageCmdFileText, &wszString[0], MAX_PATH); if (wszString[0]) { if (!(pwszUsageCmdFileText = new WCHAR[wcslen(&wszString[0]) + 1])) { return; } wcscpy(pwszUsageCmdFileText, &wszString[0]); } wszString[0] = NULL; LoadStringU(this->hInst, dwsidOptionParamText, &wszString[0], MAX_PATH); if (wszString[0]) { if (!(pwszOptionParamText = new WCHAR[wcslen(&wszString[0]) + 1])) { return; } wcscpy(pwszOptionParamText, &wszString[0]); } wszString[0] = NULL; LoadStringU(this->hInst, dwsidUsageAddText, &wszString[0], MAX_PATH); if (wszString[0]) { if (!(pwszUsageAddText = new WCHAR[wcslen(&wszString[0]) + 1])) { return; } wcscpy(pwszUsageAddText, &wszString[0]); } } WCHAR *cWArgv_::GetUsageString(void) { int i; if (pwszUsageString) { return(pwszUsageString); } if (!(pwszThisFilename)) { return(NULL); } DWORD ccLen; ccLen = wcslen(pwszThisFilename); if (pwszUsageWord) { ccLen += wcslen(pwszUsageWord); } if (pwszUsageOptionsText) { ccLen += wcslen(pwszUsageOptionsText); } if (fChkCmdF) { if (pwszUsageCmdFileText) { ccLen += wcslen(pwszUsageCmdFileText); } } if (pwszUsageAddText) { ccLen += wcslen(pwszUsageAddText); } ARGVSTORAGE *pArg; DWORD dwIdx; dwIdx = 0; while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx)) { if (pArg->dwsidOption != SID_FILES) { if (pArg->pwszOption) { if ((pArg->fHiddenCmd) && (!(fShowHiddenArgs))) { dwIdx++; continue; } ccLen += 6; // 5 spaces + 1 for '-' ccLen += dwLongestArg; // wcslen(pArg->pwszOption); if (((fNonHiddenParamArgs) && !(fShowHiddenArgs)) || (fShowHiddenArgs)) { if ((pwszNonParamArgBlanks) && (pwszOptionParamText)) { ccLen++; // space ccLen += wcslen(pwszOptionParamText); } } if (pArg->pwszOptionHelp) { ccLen += 2; // : + space ccLen += wcslen(pArg->pwszOptionHelp); } ccLen += 2; // cr/lf } } dwIdx++; } ccLen += 10; if (!(pwszUsageString = new WCHAR[ccLen + 1])) { return(NULL); } swprintf(pwszUsageString, L"%s: %s %s %s %s\r\n", pwszUsageWord, pwszThisFilename, (pwszUsageOptionsText) ? pwszUsageOptionsText : L"", (pwszUsageCmdFileText && fChkCmdF) ? pwszUsageCmdFileText : L"", (pwszUsageAddText) ? pwszUsageAddText : L""); dwIdx = pArgs->Count() - 1; while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx)) { if (pArg->dwsidOption != SID_FILES) { if (pArg->pwszOption) { if ((pArg->fHiddenCmd) && (!(fShowHiddenArgs))) { if (dwIdx == 0) { break; } dwIdx--; continue; } wcscat(pwszUsageString, L" -"); wcscat(pwszUsageString, pArg->pwszOption); if ((pArg->dwValueType != WARGV_VALUETYPE_BOOL) && (pwszOptionParamText)) { wcscat(pwszUsageString, L" "); wcscat(pwszUsageString, pwszOptionParamText); } if (pArg->pwszOptionHelp) { wcscat(pwszUsageString, L": "); for (i = 0; i < (int)(dwLongestArg - wcslen(pArg->pwszOption)); i++) { wcscat(pwszUsageString, L" "); } if ((pArg->dwValueType == WARGV_VALUETYPE_BOOL) && (((fNonHiddenParamArgs) && !(fShowHiddenArgs)) || (fShowHiddenArgs)) && (pwszNonParamArgBlanks)) { wcscat(pwszUsageString, pwszNonParamArgBlanks); } wcscat(pwszUsageString, pArg->pwszOptionHelp); } wcscat(pwszUsageString, L"\r\n"); } } if (dwIdx == 0) { break; } dwIdx--; } return(pwszUsageString); } BOOL cWArgv_::Add2List(DWORD dwsidOption, DWORD dwsidOptionHelp, DWORD dwValueType, void *pvDefaultValue, BOOL fInternalCmd) { if (!(pArgs)) { return(FALSE); } ARGVSTORAGE *pArg; WCHAR wszString[MAX_PATH]; DWORD i; if (!(pArg = (ARGVSTORAGE *)pArgs->Add(sizeof(ARGVSTORAGE)))) { return(FALSE); } memset(pArg, 0x00, sizeof(ARGVSTORAGE)); pArg->dwValueType = dwValueType; if (pArg->dwValueType != WARGV_VALUETYPE_BOOL) { if (!(pwszNonParamArgBlanks)) { if (pwszOptionParamText) { if (pwszNonParamArgBlanks = new WCHAR[wcslen(pwszOptionParamText) + 2]) { for (i = 0; i <= (DWORD)wcslen(pwszOptionParamText); i++) { pwszNonParamArgBlanks[i] = L' '; } pwszNonParamArgBlanks[i] = NULL; } } } fNonHiddenParamArgs = TRUE; } pArg->fHiddenCmd = fInternalCmd; pArg->dwsidOption = dwsidOption; wszString[0] = NULL; LoadStringU(this->hInst, dwsidOption, &wszString[0], MAX_PATH); if (wszString[0]) { if (!(pArg->pwszOption = new WCHAR[wcslen(&wszString[0]) + 1])) { return(FALSE); } wcscpy(pArg->pwszOption, &wszString[0]); if ((DWORD)wcslen(&wszString[0]) > dwLongestArg) { dwLongestArg = wcslen(&wszString[0]); } } pArg->dwsidOptionHelp = dwsidOptionHelp; wszString[0] = NULL; LoadStringU(this->hInst, dwsidOptionHelp, &wszString[0], MAX_PATH); if (wszString[0]) { if (!(pArg->pwszOptionHelp = new WCHAR[wcslen(&wszString[0]) + 1])) { return(FALSE); } wcscpy(pArg->pwszOptionHelp, &wszString[0]); } if (pvDefaultValue) { switch (dwValueType) { case WARGV_VALUETYPE_BOOL: pArg->fValue = (BOOL)((DWORD_PTR)pvDefaultValue); break; case WARGV_VALUETYPE_DWORDD: case WARGV_VALUETYPE_DWORDH: pArg->dwValue = (DWORD)((DWORD_PTR)pvDefaultValue); break; case WARGV_VALUETYPE_WCHAR: pArg->pwszValue = (WCHAR *)pvDefaultValue; break; default: return(FALSE); } } return(TRUE); } BOOL cWArgv_::Fill(int argc, WCHAR **wargv) { if (!(pArgs)) { return(FALSE); } if (!(pwszThisFilename)) { if (pwszThisFilename = wcsrchr(&wargv[0][0], L'\\')) { pwszThisFilename++; } else { pwszThisFilename = &wargv[0][0]; } } int i; for (i = 1; i < argc; ++i) { switch (wargv[i][0]) { case L'-': case L'/': if (wargv[i][1] == L'~') { fShowHiddenArgs = TRUE; return(FALSE); } i += this->ProcessArg(argc - i, &wargv[i]); break; case L'@': this->ProcessCommandFile(&wargv[i][1]); break; default: this->AddFile(&wargv[i][0]); break; } } return(TRUE); } int cWArgv_::ProcessArg(int argc, WCHAR **wargv) { ARGVSTORAGE *pArg; DWORD dwIdx; DWORD ccOption; WCHAR *pwszArg; int iRet; iRet = 0; pwszArg = &wargv[0][1]; // skip over - or / dwIdx = 0; while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx)) { if (pArg->pwszOption) { ccOption = (DWORD)wcslen(pArg->pwszOption); if (_memicmp(pArg->pwszOption, pwszArg, ccOption * sizeof(WCHAR)) == 0) { pArg->fSet = TRUE; switch (pArg->dwValueType) { case WARGV_VALUETYPE_BOOL: pArg->fValue = TRUE; return(iRet); case WARGV_VALUETYPE_DWORDH: case WARGV_VALUETYPE_DWORDD: if (!(pwszArg[ccOption])) { pwszArg = &wargv[1][0]; iRet++; } else { pwszArg = &wargv[0][ccOption + 1]; } if (pArg->dwValueType == WARGV_VALUETYPE_DWORDH) { pArg->dwValue = (DWORD)wcstoul(pwszArg, NULL, 16); } else { pArg->dwValue = (DWORD)wcstoul(pwszArg, NULL, 10); } return(iRet); case WARGV_VALUETYPE_WCHAR: if (!(pwszArg[ccOption])) { pArg->pwszValue = &wargv[1][0]; iRet++; } else { pArg->pwszValue = &wargv[0][ccOption]; } return(iRet); default: return(iRet); } } } dwIdx++; } return(iRet); } BOOL cWArgv_::IsSet(DWORD dwsidOption) { ARGVSTORAGE *pArg; DWORD dwIdx; dwIdx = 0; while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx)) { if (pArg->dwsidOption == dwsidOption) { return((pArg->fSet) ? TRUE : FALSE); } dwIdx++; } return(FALSE); } void *cWArgv_::GetValue(DWORD dwsidOption) { ARGVSTORAGE *pArg; DWORD dwIdx; dwIdx = 0; while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx)) { if (pArg->dwsidOption == dwsidOption) { switch (pArg->dwValueType) { case WARGV_VALUETYPE_BOOL: return((void *)(UINT_PTR)pArg->fValue); case WARGV_VALUETYPE_DWORDD: case WARGV_VALUETYPE_DWORDH: return((void *)(UINT_PTR)pArg->dwValue); case WARGV_VALUETYPE_WCHAR: return((void *)pArg->pwszValue); default: return(NULL); } } dwIdx++; } return(NULL); } WCHAR *cWArgv_::GetOptionHelp(DWORD dwsidOption) { if (!(pArgs)) { return(NULL); } ARGVSTORAGE *pArg; DWORD dwIdx; dwIdx = 0; while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx)) { if (pArg->dwsidOption == dwsidOption) { return(pArg->pwszOptionHelp); } dwIdx++; } return(NULL); } WCHAR *cWArgv_::GetOption(DWORD dwsidOption) { if (!(pArgs)) { return(NULL); } ARGVSTORAGE *pArg; DWORD dwIdx; dwIdx = 0; while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx)) { if (pArg->dwsidOption == dwsidOption) { return(pArg->pwszOption); } dwIdx++; } return(NULL); } WCHAR *cWArgv_::GetFileName(DWORD *pdwidxLast) { if (!(pArgs)) { return(NULL); } ARGVSTORAGE *pArg; DWORD dwIdx; DWORD dwFIdx; dwIdx = 0; dwFIdx = 1; while (pArg = (ARGVSTORAGE *)pArgs->Get(dwIdx)) { if (pArg->dwsidOption == SID_FILES) { if (!(pdwidxLast) || (dwFIdx > *pdwidxLast)) { return(pArg->pwszValue); } dwFIdx++; } dwIdx++; } return(NULL); } BOOL cWArgv_::AddFile(WCHAR *pwszFile) { ARGVSTORAGE *pArg; if (!(pArg = (ARGVSTORAGE *)pArgs->Add(sizeof(ARGVSTORAGE)))) { return(FALSE); } memset(pArg, 0x00, sizeof(ARGVSTORAGE)); pArg->dwsidOption = SID_FILES; pArg->dwValueType = WARGV_VALUETYPE_WCHAR; pArg->pwszValue = pwszFile; this->StripQuotes(pArg->pwszValue); return(TRUE); } BOOL cWArgv_::ProcessCommandFile(WCHAR *pwszFile) { if (!(this->fChkCmdF)) { return(FALSE); } HANDLE hFile; BOOL fFailed = FALSE; fParse_ fp(pwszFile, &fFailed); WCHAR *pwsz; if (fFailed) { return FALSE; } fp.Reset(); while (fp.GetNextLine()) { fp.EOLRemove(); if ((fp.GetCurrentLine()) && (fp.GetCurrentLine()[0])) { pwsz = fp.GetCurrentLine(); this->Fill(1, &pwsz); } } return(TRUE); } void cWArgv_::StripQuotes(WCHAR *pwszIn) { DWORD dwSrc; DWORD dwDst; DWORD dwLen; dwSrc = 0; dwDst = 0; dwLen = wcslen(pwszIn); while (dwSrc < dwLen) { if (pwszIn[dwSrc] != L'\"') { pwszIn[dwDst] = pwszIn[dwSrc]; dwDst++; } dwSrc++; } pwszIn[dwDst] = NULL; }