Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

755 lines
17 KiB

//+-------------------------------------------------------------------------
//
// 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;
}