388 lines
9.9 KiB
C
388 lines
9.9 KiB
C
|
/*++
|
||
|
|
||
|
UTEST.C
|
||
|
|
||
|
Test program for the options subsystem. Must compile under
|
||
|
NT and UNIX
|
||
|
|
||
|
Created, 5/24/1997 by DavidCHR
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "private.h"
|
||
|
|
||
|
optEnumStruct enums[] = {
|
||
|
|
||
|
{ "one", (PVOID) 1, "should end up 1" },
|
||
|
{ "two", (PVOID) 2, "should end up 2" },
|
||
|
{ "beef", (PVOID)(UINT_PTR)(UINT) 0xdeadbeef, "should be 0xdeadbeef" },
|
||
|
{ "beefs", (PVOID)(UINT_PTR)(UINT) 0xbadf00d, "should be 0xbadf00d" },
|
||
|
{ "secret", (PVOID) 60, }, // shouldn't show in help
|
||
|
|
||
|
TERMINATE_ARRAY
|
||
|
|
||
|
};
|
||
|
|
||
|
ULONG enumTestVariable=0;
|
||
|
|
||
|
PCHAR SubString = NULL;
|
||
|
|
||
|
|
||
|
optionStruct substructOptions[] = {
|
||
|
|
||
|
{ "h", NULL, OPT_HELP },
|
||
|
{ "substr", &SubString, OPT_STRING, "Substring option" },
|
||
|
|
||
|
TERMINATE_ARRAY
|
||
|
};
|
||
|
|
||
|
PCHAR FuncString1 = NULL;
|
||
|
PCHAR FuncString2 = NULL;
|
||
|
PCHAR StringOption = NULL;
|
||
|
int IntegerOption = 0L;
|
||
|
BOOL BooleanOption = FALSE;
|
||
|
float FloatOption = 0.0;
|
||
|
PCHAR UndocumentedString = NULL;
|
||
|
PWCHAR WideCharOption = NULL;
|
||
|
UNICODE_STRING UnicodeStringOption = { 0 };
|
||
|
|
||
|
int MyOptFunc( IN int argc,
|
||
|
IN PCHAR *argv );
|
||
|
BOOL MyOptFunc2( IN BOOL fHelp,
|
||
|
IN POPT_FUNC_PARAMETER_DATA pData );
|
||
|
|
||
|
optionStruct sampleOptions[ ] = {
|
||
|
|
||
|
{ "help", NULL, OPT_HELP },
|
||
|
{ "?", NULL, OPT_HELP },
|
||
|
|
||
|
{ NULL, NULL, OPT_DUMMY, "-----------------------------" },
|
||
|
{ NULL, NULL, OPT_CONTINUE, "These are the useful options:" },
|
||
|
{ NULL, NULL, OPT_DUMMY, "-----------------------------" },
|
||
|
|
||
|
{ "enum", &enumTestVariable, OPT_ENUMERATED,
|
||
|
"Test enumerated type", enums },
|
||
|
|
||
|
{ "mask", &enumTestVariable, OPT_ENUMERATED | OPT_ENUM_IS_MASK,
|
||
|
"Test enumerated type with OPT_ENUM_IS_MASK", enums },
|
||
|
|
||
|
{ "substruct", substructOptions, OPT_SUBOPTION | OPT_RECURSE,
|
||
|
"substruct:help for help" },
|
||
|
{ "recurse", sampleOptions, OPT_SUBOPTION, "recurse:help for help" },
|
||
|
|
||
|
{ "string", &StringOption, OPT_STRING | OPT_ENVIRONMENT, "String Option",
|
||
|
"StringOption" },
|
||
|
|
||
|
{ NULL, NULL, OPT_CONTINUE, "Use this option to request a string" },
|
||
|
|
||
|
{ "int", &IntegerOption, OPT_INT | OPT_ENVIRONMENT, "integer option",
|
||
|
"IntegerOption" },
|
||
|
|
||
|
{ NULL, NULL, OPT_CONTINUE, "Use this option to request an integer" },
|
||
|
|
||
|
{ "func", MyOptFunc, OPT_FUNC, "function option" },
|
||
|
{ NULL, NULL, OPT_CONTINUE, "Use this option to request two strings" },
|
||
|
|
||
|
{ "func2", &IntegerOption, OPT_FUNC2, "FUNC2 option",
|
||
|
MyOptFunc2 },
|
||
|
|
||
|
{ "bool", &BooleanOption, OPT_BOOL, "boolean option" },
|
||
|
{ NULL, NULL, OPT_CONTINUE, "Use this option to request a boolean" },
|
||
|
|
||
|
{ "float", &FloatOption, OPT_FLOAT, "floating point option" },
|
||
|
{ NULL, NULL, OPT_CONTINUE, "Use this option to request a float" },
|
||
|
|
||
|
{ "wstring",&WideCharOption, OPT_WSTRING | OPT_ENVIRONMENT,
|
||
|
"Wide Char String option", "WideCharOption" },
|
||
|
|
||
|
{ "ustring",&UnicodeStringOption, OPT_USTRING | OPT_ENVIRONMENT,
|
||
|
"Unicode String Option", "UnicodeStringOption" },
|
||
|
|
||
|
{ "hidden", &UndocumentedString, OPT_STRING | OPT_HIDDEN,
|
||
|
"you should never see this line. This option is OPT_HIDDEN" },
|
||
|
|
||
|
{ "stop", NULL, OPT_STOP_PARSING,
|
||
|
"halts parsing of the command line." },
|
||
|
|
||
|
{ NULL, NULL, OPT_DUMMY | OPT_NOHEADER, "" },
|
||
|
|
||
|
{ NULL, NULL, OPT_DUMMY | OPT_NOHEADER,
|
||
|
"Example: utest /string \"foo bar baz\" /int 0x15 +bool /float 3.14" },
|
||
|
|
||
|
{ NULL, NULL, OPT_PAUSE },
|
||
|
|
||
|
TERMINATE_ARRAY
|
||
|
|
||
|
};
|
||
|
|
||
|
int
|
||
|
MyOptFunc( int argc,
|
||
|
PCHAR *argv ) {
|
||
|
|
||
|
if ( ( argv == NULL ) || (argc < 3 ) ) {
|
||
|
/* this means the user requested help */
|
||
|
fprintf( stderr, "func [string1] [string2]\n" );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
printf( "MyOptFunc was called. argc=%d.\n", argc );
|
||
|
|
||
|
FuncString1 = argv[1];
|
||
|
FuncString2 = argv[2];
|
||
|
|
||
|
return 3; /* number of arguments eaten--
|
||
|
-func argv[1] argv[2] == 3 options */
|
||
|
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
DumpArgs( int argc,
|
||
|
PCHAR argv[] ) {
|
||
|
|
||
|
int i;
|
||
|
|
||
|
for ( i = 0 ; i < argc ; i++ ) {
|
||
|
fprintf( stderr, "arg %d = %s\n", i, argv[i] );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
MyOptFunc2( IN BOOL fHelp,
|
||
|
IN POPT_FUNC_PARAMETER_DATA pData ) {
|
||
|
|
||
|
#if OPT_FUNC_PARAMETER_VERSION != 1
|
||
|
#error "OptFuncParameterVersion has changed. Update this function."
|
||
|
#endif
|
||
|
|
||
|
optionStruct OptFunc2Options[] = {
|
||
|
|
||
|
{ "help", NULL, OPT_HELP },
|
||
|
{ "FuncString1", &FuncString1, OPT_INT },
|
||
|
{ "FuncString2", &FuncString2, OPT_INT },
|
||
|
{ "recurse", sampleOptions, OPT_SUBOPTION,
|
||
|
"points back to the toplevel structure. Very amusing. :-)" },
|
||
|
{ "STOP", NULL, OPT_STOP_PARSING,
|
||
|
"halts parsing within the Func2." },
|
||
|
|
||
|
TERMINATE_ARRAY
|
||
|
|
||
|
};
|
||
|
|
||
|
if ( fHelp ) {
|
||
|
|
||
|
CHAR buffer[ 255 ];
|
||
|
|
||
|
PrintUsageEntry( stderr,
|
||
|
"[-/+]", // switch characters
|
||
|
pData->argv[0], // command GUARANTEED TO EXIST
|
||
|
"->", // separator
|
||
|
"Exercises the OPT_FUNC2 interface. Options follow",
|
||
|
FALSE ); // FALSE--> do not repeat switch.
|
||
|
|
||
|
sprintf( buffer, "-> options %s takes ", pData->argv[0] );
|
||
|
|
||
|
PrintUsageEntry( stderr,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
"-=", // the NULLs will fill with this string.
|
||
|
buffer,
|
||
|
TRUE );
|
||
|
|
||
|
sprintf( buffer, "(%s) ", pData->argv[0] );
|
||
|
|
||
|
PrintUsage( stderr,
|
||
|
0L, // flags
|
||
|
OptFunc2Options,
|
||
|
buffer );
|
||
|
|
||
|
PrintUsageEntry( stderr,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
"-*",
|
||
|
"-> (end of OPT_FUNC2 options)",
|
||
|
TRUE );
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if ( pData->optionVersion != OPT_FUNC_PARAMETER_VERSION ) {
|
||
|
fprintf( stderr,
|
||
|
"WARNING: option library out of sync with header\n" );
|
||
|
}
|
||
|
|
||
|
fprintf( stderr,
|
||
|
"MyOptFunc2 called. Data follows:\n"
|
||
|
"pData->optionVersion = %d\n"
|
||
|
"pData->dataField = 0x%p\n"
|
||
|
"pData->argc = %d\n"
|
||
|
"pData->argv = 0x%p\n"
|
||
|
"pData->optionFlags = 0x%x\n"
|
||
|
"pData->pSaveQueue = 0x%p\n",
|
||
|
|
||
|
pData->optionVersion,
|
||
|
pData->dataFieldPointer,
|
||
|
pData->argc,
|
||
|
pData->argv,
|
||
|
pData->optionFlags,
|
||
|
pData->pSaveQueue );
|
||
|
|
||
|
fprintf( stderr, "%s arguments are:\n", pData->argv[0] );
|
||
|
|
||
|
DumpArgs( pData->argc, pData->argv );
|
||
|
|
||
|
if ( ParseOptionsEx( pData->argc-1,
|
||
|
pData->argv+1,
|
||
|
OptFunc2Options,
|
||
|
pData->optionFlags,
|
||
|
&pData->pSaveQueue,
|
||
|
&pData->argsused,
|
||
|
&pData->argv ) ) {
|
||
|
|
||
|
fprintf( stderr,
|
||
|
"pData->argsused IN = %d\n", pData->argsused );
|
||
|
|
||
|
pData->argsused = pData->argc - pData->argsused;
|
||
|
|
||
|
fprintf( stderr,
|
||
|
"pData->argsused OUT = %d\n", pData->argsused );
|
||
|
|
||
|
} else return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
fprintf( stderr, "\n Leaving OPT_FUNC2. \n\n" );
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
__cdecl
|
||
|
main( int argc,
|
||
|
char *argv[] ) {
|
||
|
|
||
|
BOOL foo;
|
||
|
PVOID pCleanup = NULL;
|
||
|
optEnumStruct parserOptions[] = {
|
||
|
|
||
|
{ "skip", (PVOID) OPT_FLAG_SKIP_UNKNOWNS,
|
||
|
"OPT_FLAG_SKIP_UNKNOWNS" },
|
||
|
{ "reassemble", (PVOID) OPT_FLAG_REASSEMBLE,
|
||
|
"OPT_FLAG_REASSEMBLE" },
|
||
|
{ "terminate", (PVOID) OPT_FLAG_TERMINATE,
|
||
|
"OPT_FLAG_TERMINATE" },
|
||
|
|
||
|
TERMINATE_ARRAY
|
||
|
};
|
||
|
|
||
|
ULONG ParserFlag = OPT_FLAG_REASSEMBLE;
|
||
|
|
||
|
#ifndef DEBUG_OPTIONS
|
||
|
BOOL DebugFlag = 0; // will be ignored... just here for convenience
|
||
|
#endif
|
||
|
optionStruct singleOption[] = {
|
||
|
|
||
|
{ "utestHelp", NULL, OPT_HELP },
|
||
|
|
||
|
{ "parserFlag", &ParserFlag, OPT_ENUMERATED,
|
||
|
"flags to pass to ParseOptionsEx", parserOptions },
|
||
|
{ "headerlength", &OptMaxHeaderLength, OPT_INT,
|
||
|
"OptMaxHeaderLength value (formatting)" },
|
||
|
{ "commandLength", &OptMaxCommandLength, OPT_INT,
|
||
|
"OptMaxCommandLength value (formatting)" },
|
||
|
{ "separatorLength", &OptMaxSeparatorLength, OPT_INT,
|
||
|
"OptMaxSeparatorLength value (formatting)" },
|
||
|
{ "descriptionLength", &OptMaxDescriptionLength, OPT_INT,
|
||
|
"OptMaxDescriptionLength value (formatting)" },
|
||
|
{ "debug", &DebugFlag, OPT_INT, "Debugger status" },
|
||
|
|
||
|
TERMINATE_ARRAY
|
||
|
|
||
|
};
|
||
|
|
||
|
DebugFlag |= OPTION_DEBUGGING_LEVEL;
|
||
|
|
||
|
foo = ParseOptionsEx( argc-1, argv+1, singleOption,
|
||
|
0, &pCleanup, &argc, &argv );
|
||
|
|
||
|
ParserFlag |= OPT_FLAG_MEMORYLIST_OK;
|
||
|
|
||
|
fprintf( stderr,
|
||
|
|
||
|
"first ParseOptionsEx returned 0x%x \n"
|
||
|
" saveQueue 0x%p \n"
|
||
|
" passing in flags 0x%x \n",
|
||
|
|
||
|
foo, pCleanup, ParserFlag );
|
||
|
|
||
|
if ( argc ) {
|
||
|
|
||
|
ULONG i;
|
||
|
|
||
|
fprintf( stderr, "%d new options: \n", argc );
|
||
|
DumpArgs( argc, argv );
|
||
|
|
||
|
fprintf( stderr, "\n" );
|
||
|
}
|
||
|
|
||
|
foo = ParseOptionsEx( argc, argv, sampleOptions, ParserFlag,
|
||
|
&pCleanup, &argc, &argv );
|
||
|
|
||
|
fprintf( stderr,
|
||
|
"ParseOptionsEx returns %d\n"
|
||
|
" new argv = 0x%p\n"
|
||
|
" new argc = %d \n",
|
||
|
foo, argv, argc );
|
||
|
|
||
|
|
||
|
DumpArgs( argc, argv );
|
||
|
|
||
|
printf( "Formatting values were:\n"
|
||
|
"\tOptMaxHeaderLength = %d\n"
|
||
|
"\tOptMaxCommandLength = %d\n"
|
||
|
"\tOptMaxSeparatorLength = %d\n"
|
||
|
"\tOptMaxDescriptionLength = %d\n",
|
||
|
|
||
|
OptMaxHeaderLength,
|
||
|
OptMaxCommandLength,
|
||
|
OptMaxSeparatorLength,
|
||
|
OptMaxDescriptionLength );
|
||
|
|
||
|
printf( "\nOptions used:\n"
|
||
|
"\tstring = \"%hs\"\n"
|
||
|
"\tint = %d \n"
|
||
|
"\tBool = 0x%x \n"
|
||
|
/* "Float = %f \n" */
|
||
|
"\twstring = L\"%ws\"\n"
|
||
|
"\tustring = (unicode string) %wZ \n"
|
||
|
"\thidden = \"%hs\"\n"
|
||
|
"\tsubstruct:substr = \"%hs\"\n"
|
||
|
"\tfuncString1 = \"%hs\"\n"
|
||
|
"\tfuncString2 = \"%hs\"\n"
|
||
|
"\tenum = %d (0x%x)\n",
|
||
|
|
||
|
StringOption,
|
||
|
IntegerOption,
|
||
|
BooleanOption,
|
||
|
/* FloatOption, */ /* floating point not loaded?
|
||
|
What does that mean?! */
|
||
|
WideCharOption,
|
||
|
&UnicodeStringOption,
|
||
|
UndocumentedString,
|
||
|
SubString,
|
||
|
|
||
|
FuncString1,
|
||
|
FuncString2,
|
||
|
|
||
|
enumTestVariable, enumTestVariable );
|
||
|
|
||
|
CleanupOptionDataEx( pCleanup );
|
||
|
|
||
|
return foo;
|
||
|
|
||
|
}
|
||
|
|