243 lines
6.2 KiB
C
243 lines
6.2 KiB
C
|
/*** parsearg.c - Library functions for parsing command line arguments
|
||
|
*
|
||
|
* Copyright (c) 1996,1997 Microsoft Corporation
|
||
|
* Author: Michael Tsang (MikeTs)
|
||
|
* Created: 09/05/96
|
||
|
*
|
||
|
* This module provides general purpose services to parse
|
||
|
* command line arguments.
|
||
|
*
|
||
|
* MODIFICATION HISTORY
|
||
|
*/
|
||
|
|
||
|
#include "basedef.h"
|
||
|
#include "parsearg.h"
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
/*** Local function prototypes
|
||
|
*/
|
||
|
|
||
|
int LOCAL ParseArgSwitch(char **, PARGTYPE, PPROGINFO);
|
||
|
VOID LOCAL PrintError(int, char *, PPROGINFO);
|
||
|
|
||
|
/***EP ParseProgInfo - parse program path and module name
|
||
|
*
|
||
|
* ENTRY
|
||
|
* pszArg0 -> argument 0
|
||
|
* pPI -> program info structure
|
||
|
*
|
||
|
* EXIT
|
||
|
* None
|
||
|
*/
|
||
|
|
||
|
VOID EXPORT ParseProgInfo(char *pszArg0, PPROGINFO pPI)
|
||
|
{
|
||
|
char *pch;
|
||
|
|
||
|
pPI->pszProgPath = _strlwr(pszArg0);
|
||
|
if ((pch = strrchr(pszArg0, '\\')) != NULL)
|
||
|
{
|
||
|
*pch = '\0';
|
||
|
pPI->pszProgName = pch + 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pPI->pszProgName = pszArg0;
|
||
|
}
|
||
|
|
||
|
if ((pch = strchr(pPI->pszProgName, '.')) != NULL)
|
||
|
*pch = '\0';
|
||
|
} //ParseProgInfo
|
||
|
|
||
|
/***EP ParseSwitches - parse command switches
|
||
|
*
|
||
|
* ENTRY
|
||
|
* pcArg -> argument count
|
||
|
* pppszArg -> pointer to array of pointers to argument strings
|
||
|
* pAT -> argument type array
|
||
|
* pPI -> program info. structure
|
||
|
*
|
||
|
* EXIT-SUCCESS
|
||
|
* returns ARGERR_NONE
|
||
|
* EXIT-FAILURE
|
||
|
* returns error code, *pppszArg -> error argument
|
||
|
*/
|
||
|
|
||
|
int EXPORT ParseSwitches(int *pcArg, char ***pppszArg, PARGTYPE pAT, PPROGINFO pPI)
|
||
|
{
|
||
|
int rc = ARGERR_NONE;
|
||
|
char *pszArg;
|
||
|
|
||
|
if (pPI->pszSwitchChars == NULL)
|
||
|
pPI->pszSwitchChars = DEF_SWITCHCHARS;
|
||
|
|
||
|
if (pPI->pszSeparators == NULL)
|
||
|
pPI->pszSeparators = DEF_SEPARATORS;
|
||
|
|
||
|
for (; *pcArg; (*pcArg)--, (*pppszArg)++)
|
||
|
{
|
||
|
pszArg = **pppszArg;
|
||
|
if (strchr(pPI->pszSwitchChars, *pszArg))
|
||
|
{
|
||
|
pszArg++;
|
||
|
if ((rc = ParseArgSwitch(&pszArg, pAT, pPI)) != ARGERR_NONE)
|
||
|
{
|
||
|
PrintError(rc, pszArg, pPI);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return rc;
|
||
|
} //ParseSwitches
|
||
|
|
||
|
|
||
|
/***LP ParseArgSwitch - parse a command line switch
|
||
|
*
|
||
|
* ENTRY
|
||
|
* ppszArg -> pointer to argument
|
||
|
* pAT -> argument type table
|
||
|
* pPI -> program info. structure
|
||
|
*
|
||
|
* EXIT
|
||
|
* return argument parsed status - ARGERR_NONE
|
||
|
* - ARGERR_UNKNOWN_SWITCH
|
||
|
* - ARGERR_INVALID_NUM
|
||
|
* - ARGERR_NO_SEPARATOR
|
||
|
* - ARGERR_INVALID_TAIL
|
||
|
*/
|
||
|
|
||
|
int LOCAL ParseArgSwitch(char **ppszArg, PARGTYPE pAT, PPROGINFO pPI)
|
||
|
{
|
||
|
int rc = ARGERR_NONE;
|
||
|
char *pEnd;
|
||
|
PARGTYPE pAT1;
|
||
|
int fFound = FALSE;
|
||
|
int lenMatch = 0;
|
||
|
|
||
|
pAT1 = pAT;
|
||
|
while (pAT1->pszArgID[0])
|
||
|
{
|
||
|
lenMatch = strlen(pAT1->pszArgID);
|
||
|
if (pAT1->uParseFlags & PF_NOI)
|
||
|
fFound = (strncmp(pAT1->pszArgID, *ppszArg, lenMatch) == 0);
|
||
|
else
|
||
|
fFound = (_strnicmp(pAT1->pszArgID, *ppszArg, lenMatch) == 0);
|
||
|
|
||
|
if (fFound)
|
||
|
break;
|
||
|
else
|
||
|
pAT1++;
|
||
|
}
|
||
|
|
||
|
if (fFound)
|
||
|
{
|
||
|
*ppszArg += lenMatch;
|
||
|
switch (pAT1->uArgType)
|
||
|
{
|
||
|
case AT_STRING:
|
||
|
case AT_NUM:
|
||
|
if (pAT1->uParseFlags & PF_SEPARATOR)
|
||
|
{
|
||
|
if (**ppszArg && strchr(pPI->pszSeparators, **ppszArg))
|
||
|
(*ppszArg)++;
|
||
|
else
|
||
|
{
|
||
|
rc = ARGERR_NO_SEPARATOR;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pAT1->uArgType == AT_STRING)
|
||
|
*(char **)pAT1->pvArgData = *ppszArg;
|
||
|
else
|
||
|
{
|
||
|
*(int *)pAT1->pvArgData = (int)
|
||
|
strtol(*ppszArg, &pEnd, pAT1->uArgParam);
|
||
|
if (*ppszArg == pEnd)
|
||
|
{
|
||
|
rc = ARGERR_INVALID_NUM;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
*ppszArg = pEnd;
|
||
|
}
|
||
|
if (pAT1->pfnArgVerify)
|
||
|
rc = (*pAT1->pfnArgVerify)(ppszArg, pAT1);
|
||
|
break;
|
||
|
|
||
|
case AT_ENABLE:
|
||
|
case AT_DISABLE:
|
||
|
if (pAT1->uArgType == AT_ENABLE)
|
||
|
*(unsigned *)pAT1->pvArgData |= pAT1->uArgParam;
|
||
|
else
|
||
|
*(unsigned *)pAT1->pvArgData &= ~pAT1->uArgParam;
|
||
|
|
||
|
if ((pAT1->pfnArgVerify) &&
|
||
|
((rc = (*pAT1->pfnArgVerify)(ppszArg, pAT1)) !=
|
||
|
ARGERR_NONE))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (**ppszArg)
|
||
|
{
|
||
|
if (strchr(pPI->pszSwitchChars, **ppszArg))
|
||
|
(*ppszArg)++;
|
||
|
rc = ParseArgSwitch(ppszArg, pAT, pPI);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case AT_ACTION:
|
||
|
#pragma warning(disable: 4055)
|
||
|
rc = (*(PFNARG)pAT1->pvArgData)(ppszArg, pAT1);
|
||
|
#pragma warning(default: 4055)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
rc = ARGERR_UNKNOWN_SWITCH;
|
||
|
|
||
|
return rc;
|
||
|
} //ParseArgSwitch
|
||
|
|
||
|
|
||
|
/***LP PrintError - print appropriate error message according to error code
|
||
|
*
|
||
|
* ENTRY
|
||
|
* iErr = error code
|
||
|
* pszArg -> argument in error
|
||
|
* pPI -> program info. structure
|
||
|
*
|
||
|
* EXIT
|
||
|
* None
|
||
|
*/
|
||
|
|
||
|
VOID LOCAL PrintError(int iErr, char *pszArg, PPROGINFO pPI)
|
||
|
{
|
||
|
switch (iErr)
|
||
|
{
|
||
|
case ARGERR_UNKNOWN_SWITCH:
|
||
|
printf("%s: unknown switch \"%s\"\n", pPI->pszProgName, pszArg);
|
||
|
break;
|
||
|
|
||
|
case ARGERR_NO_SEPARATOR:
|
||
|
printf("%s: separator missing after the switch char '%c'\n",
|
||
|
pPI->pszProgName, *(pszArg-1));
|
||
|
break;
|
||
|
|
||
|
case ARGERR_INVALID_NUM:
|
||
|
printf("%s: invalid numeric switch \"%s\"\n",
|
||
|
pPI->pszProgName, pszArg);
|
||
|
break;
|
||
|
|
||
|
case ARGERR_INVALID_TAIL:
|
||
|
printf("%s: invalid argument tail \"%s\"\n",
|
||
|
pPI->pszProgName, pszArg);
|
||
|
}
|
||
|
} //PrintError
|