397 lines
7.4 KiB
C
397 lines
7.4 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
parsearg.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Argument Handling
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
MikeTs
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Any
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "pch.h"
|
|||
|
|
|||
|
//
|
|||
|
// Local function prototypes
|
|||
|
//
|
|||
|
ULONG
|
|||
|
LOCAL
|
|||
|
ParseArgSwitch(
|
|||
|
PUCHAR *Argument,
|
|||
|
PARGTYPE ArgumentArray,
|
|||
|
PPROGINFO ProgramInfo
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
LOCAL
|
|||
|
PrintError(
|
|||
|
ULONG ErrorCode,
|
|||
|
PUCHAR Argument,
|
|||
|
PPROGINFO ProgramInfo
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
EXPORT
|
|||
|
ParseProgramInfo(
|
|||
|
PUCHAR ProgramName,
|
|||
|
PPROGINFO ProgramInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine parses program path and module name
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ProgramName - The Argv[0] from main()
|
|||
|
ProgramInfo - Program Information structure
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PUCHAR ptr;
|
|||
|
|
|||
|
ProgramInfo->ProgPath = _strlwr(ProgramName);
|
|||
|
ptr = strrchr( ProgramName, '\\' );
|
|||
|
if (ptr != NULL) {
|
|||
|
|
|||
|
*ptr = '\0';
|
|||
|
ProgramInfo->ProgName = ptr + 1;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
ProgramInfo->ProgName = ProgramName;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ptr = strchr(ProgramInfo->ProgName, '.');
|
|||
|
if (ptr != NULL) {
|
|||
|
|
|||
|
*ptr = '\0';
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
EXPORT
|
|||
|
ParseSwitches(
|
|||
|
PULONG ArgumentCount,
|
|||
|
PUCHAR **ArgumentList,
|
|||
|
PARGTYPE ArgumentArray,
|
|||
|
PPROGINFO ProgramInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Parse command line switches
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ArgumentCount - Pointer to the number of arguments
|
|||
|
ArgumentList - Pointer to the pointer to the list of arguments
|
|||
|
ArgumentArray - How to parse the arguments
|
|||
|
ProgramInfo - Program Specific structure
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ULONG - Success = ARGERR_NONE
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PUCHAR argument;
|
|||
|
ULONG status = ARGERR_NONE;
|
|||
|
|
|||
|
if (ProgramInfo->SwitchChars == NULL) {
|
|||
|
|
|||
|
ProgramInfo->SwitchChars = DEF_SWITCHCHARS;
|
|||
|
|
|||
|
}
|
|||
|
if (ProgramInfo->Separators == NULL) {
|
|||
|
|
|||
|
ProgramInfo->Separators = DEF_SEPARATORS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
for (; *ArgumentCount; (*ArgumentCount)--, (*ArgumentList)++)
|
|||
|
{
|
|||
|
argument = **ArgumentList;
|
|||
|
|
|||
|
if (strchr(ProgramInfo->SwitchChars, *argument)) {
|
|||
|
|
|||
|
argument++;
|
|||
|
status = ParseArgSwitch(
|
|||
|
&argument,
|
|||
|
ArgumentArray,
|
|||
|
ProgramInfo
|
|||
|
);
|
|||
|
if (status != ARGERR_NONE) {
|
|||
|
|
|||
|
PrintError( status, argument, ProgramInfo );
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
LOCAL
|
|||
|
ParseArgSwitch(
|
|||
|
PUCHAR *Argument,
|
|||
|
PARGTYPE ArgumentArray,
|
|||
|
PPROGINFO ProgramInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Parse a command line switch
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
Argument - Pointer to argument
|
|||
|
ArgumentArray - How to handle the argument
|
|||
|
ProgramInfo - Program Information Structure
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ULONG
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL found = FALSE;
|
|||
|
PARGTYPE tableEntry;
|
|||
|
PUCHAR argumentEnd;
|
|||
|
ULONG length = 0;
|
|||
|
ULONG status = ARGERR_NONE;
|
|||
|
|
|||
|
tableEntry = ArgumentArray;
|
|||
|
while (tableEntry->ArgID[0]) {
|
|||
|
|
|||
|
length = strlen(tableEntry->ArgID);
|
|||
|
if (tableEntry->ParseFlags & PF_NOI) {
|
|||
|
|
|||
|
found = (strncmp(tableEntry->ArgID, *Argument, length) == 0);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
found = (_strnicmp(tableEntry->ArgID, *Argument, length) == 0);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (found) {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
tableEntry++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (found) {
|
|||
|
|
|||
|
*Argument += length;
|
|||
|
switch (tableEntry->ArgType) {
|
|||
|
case AT_STRING:
|
|||
|
case AT_NUM:
|
|||
|
if (tableEntry->ParseFlags & PF_SEPARATOR)
|
|||
|
{
|
|||
|
if (**Argument &&
|
|||
|
strchr(ProgramInfo->Separators, **Argument)) {
|
|||
|
|
|||
|
(*Argument)++;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = ARGERR_NO_SEPARATOR;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
if (tableEntry->ArgType == AT_STRING) {
|
|||
|
|
|||
|
*(UCHAR **)tableEntry->ArgData = *Argument;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
*(ULONG *)tableEntry->ArgData = (ULONG)
|
|||
|
strtoul(*Argument, &argumentEnd, tableEntry->ArgParam);
|
|||
|
if (*Argument == argumentEnd) {
|
|||
|
|
|||
|
status = ARGERR_INVALID_NUM;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
*Argument = argumentEnd;
|
|||
|
|
|||
|
}
|
|||
|
if (tableEntry->ArgVerify) {
|
|||
|
|
|||
|
status = (*tableEntry->ArgVerify)(Argument, tableEntry);
|
|||
|
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case AT_ENABLE:
|
|||
|
case AT_DISABLE:
|
|||
|
if (tableEntry->ArgType == AT_ENABLE) {
|
|||
|
|
|||
|
*(ULONG *)tableEntry->ArgData |= tableEntry->ArgParam;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
*(ULONG *)tableEntry->ArgData &= ~tableEntry->ArgParam;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if ( tableEntry->ArgVerify) {
|
|||
|
|
|||
|
status = (*tableEntry->ArgVerify)(Argument, tableEntry);
|
|||
|
if (status == ARGERR_NONE) {
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (**Argument) {
|
|||
|
|
|||
|
if (strchr(ProgramInfo->SwitchChars, **Argument)) {
|
|||
|
|
|||
|
(*Argument)++;
|
|||
|
|
|||
|
}
|
|||
|
status = ParseArgSwitch(
|
|||
|
Argument,
|
|||
|
ArgumentArray,
|
|||
|
ProgramInfo
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case AT_ACTION:
|
|||
|
if (tableEntry->ParseFlags & PF_SEPARATOR)
|
|||
|
{
|
|||
|
if (**Argument &&
|
|||
|
strchr(ProgramInfo->Separators, **Argument)) {
|
|||
|
|
|||
|
(*Argument)++;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = ARGERR_NO_SEPARATOR;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#pragma warning(disable: 4055)
|
|||
|
status = (*(PFNARG)tableEntry->ArgData)(Argument, tableEntry);
|
|||
|
#pragma warning(default: 4055)
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
status = ARGERR_UNKNOWN_SWITCH;
|
|||
|
|
|||
|
}
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
LOCAL
|
|||
|
PrintError(
|
|||
|
ULONG ErrorCode,
|
|||
|
PUCHAR Argument,
|
|||
|
PPROGINFO ProgramInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Print Appropriate Error Message according to error code
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ErrorCode - The error which occured
|
|||
|
Argument - Argument in Error
|
|||
|
ProgramInfo - Program info structure
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
VOID
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
switch (ErrorCode) {
|
|||
|
case ARGERR_UNKNOWN_SWITCH:
|
|||
|
fprintf(
|
|||
|
stderr,
|
|||
|
"%s: unknown switch \"%s\"\n",
|
|||
|
ProgramInfo->ProgName,
|
|||
|
Argument
|
|||
|
);
|
|||
|
break;
|
|||
|
|
|||
|
case ARGERR_NO_SEPARATOR:
|
|||
|
fprintf(
|
|||
|
stderr,
|
|||
|
"%s: separator missing after the switch char '%c'\n",
|
|||
|
ProgramInfo->ProgName,
|
|||
|
*(Argument-1)
|
|||
|
);
|
|||
|
break;
|
|||
|
|
|||
|
case ARGERR_INVALID_NUM:
|
|||
|
fprintf(
|
|||
|
stderr,
|
|||
|
"%s: invalid numeric switch \"%s\"\n",
|
|||
|
ProgramInfo->ProgName,
|
|||
|
Argument
|
|||
|
);
|
|||
|
break;
|
|||
|
|
|||
|
case ARGERR_INVALID_TAIL:
|
|||
|
fprintf(
|
|||
|
stderr,
|
|||
|
"%s: invalid argument tail \"%s\"\n",
|
|||
|
ProgramInfo->ProgName,
|
|||
|
Argument
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|