/*++ Copyright (c) 1990 Microsoft Corporation Module Name: Argument Abstract: Argument processing for the "MORE" pager Author: Ramon Juan San Andres (ramonsa) 24-Apr-1990 Notes: The arguments accepted by the more pager are: Extended mode switch.- This allows all other options. Without this switch, no other options are allowed. Help switch.- Displays usage. ClearScreen switch.- Clears the screen before displaying each page. SqueezeBlank switch.- Squeezes consecutive blank lines into a single line. ExpandFormFeed switch.- FormFeeds are expanded to fill the rest of the screen. Start at line.- Paging starts at the specified line of the first file. Tab expansion.- Expand tabs to this number of blanks File list.- List of files to page. The more pager obtains its arguments from two sources: 1.- An environment variable ( "MORE" ) 2.- The command line. The environment variable may specify any options, except a file list. Revision History: --*/ #include "ulib.hxx" #include "arg.hxx" #include "arrayit.hxx" #include "rtmsg.h" #include "path.hxx" #include "smsg.hxx" #include "system.hxx" #include "more.hxx" #define ENABLE_EXTENSIONS_VALUE L"EnableExtensions" #define COMMAND_PROCESSOR_KEY L"Software\\Microsoft\\Command Processor" // // Static variables // // PFLAG_ARGUMENT ExtendedModeArgument; PFLAG_ARGUMENT ClearScreenArgument; PFLAG_ARGUMENT ExpandFormFeedArgument; PFLAG_ARGUMENT SqueezeBlanksArgument; PFLAG_ARGUMENT Help1Argument; PFLAG_ARGUMENT Help2Argument; PLONG_ARGUMENT StartAtLineArgument; PLONG_ARGUMENT TabExpArgument; VOID MORE::SetArguments( ) /*++ Routine Description: Obtains the arguments for the "more" pager. Arguments: None. Return Value: None. Notes: --*/ { FLAG_ARGUMENT LocalExtendedModeArgument; FLAG_ARGUMENT LocalClearScreenArgument; FLAG_ARGUMENT LocalExpandFormFeedArgument; FLAG_ARGUMENT LocalSqueezeBlanksArgument; FLAG_ARGUMENT LocalHelp1Argument; FLAG_ARGUMENT LocalHelp2Argument; LONG_ARGUMENT LocalStartAtLineArgument; LONG_ARGUMENT LocalTabExpArgument; ExtendedModeArgument = &LocalExtendedModeArgument; ClearScreenArgument = &LocalClearScreenArgument; ExpandFormFeedArgument = &LocalExpandFormFeedArgument; SqueezeBlanksArgument = &LocalSqueezeBlanksArgument; Help1Argument = &LocalHelp1Argument; Help2Argument = &LocalHelp2Argument; StartAtLineArgument = &LocalStartAtLineArgument; TabExpArgument = &LocalTabExpArgument; // // Get arguments from the environment variable // GetArgumentsMore(); // // Get the arguments from the command line. // GetArgumentsCmd(); // // Determine if there is a need to enable command extension // GetRegistryInfo(); // // Verify the arguments // CheckArgumentConsistency(); } VOID MORE::GetArgumentsMore( ) /*++ Routine Description: Obtains the arguments from the "More" environment variable. Arguments: None. Return Value: None. Notes: --*/ { ARRAY ArgArray; PWSTRING MoreVariableName; PWSTRING MoreVariableValue; // // Get the name of the MORE environment variable and the argument // if ( (MoreVariableName = QueryMessageString( MORE_ENVIRONMENT_VARIABLE_NAME )) == NULL ) { Fatal(); } // // Get the value of the MORE environment variable. // MoreVariableValue = SYSTEM::QueryEnvironmentVariable( MoreVariableName ); if ( MoreVariableValue != NULL ) { // // Now prepare for parsing // if ( // // Initialize tha arguments // !(ArgArray.Initialize( 7, 7 )) || !(ExtendedModeArgument->Initialize( "/E" )) || !(ClearScreenArgument->Initialize( "/C" )) || !(ExpandFormFeedArgument->Initialize( "/P" )) || !(SqueezeBlanksArgument->Initialize( "/S" )) || !(Help1Argument->Initialize( "/?" )) || !(Help2Argument->Initialize( "/H" )) || !(StartAtLineArgument->Initialize( "+*" )) || !(TabExpArgument->Initialize( "/t*" )) || // // Put the arguments in the argument array // !(ArgArray.Put( ExtendedModeArgument )) || !(ArgArray.Put( ClearScreenArgument )) || !(ArgArray.Put( ExpandFormFeedArgument )) || !(ArgArray.Put( SqueezeBlanksArgument )) || !(ArgArray.Put( Help1Argument )) || !(ArgArray.Put( Help2Argument )) || !(ArgArray.Put( StartAtLineArgument )) || !(ArgArray.Put( TabExpArgument )) ) { Fatal(); } // // Parse the arguments // ParseArguments( MoreVariableValue, &ArgArray ); // // Set the global structures // _ExtendedModeSwitch = ExtendedModeArgument->QueryFlag(); _ClearScreenSwitch = ClearScreenArgument->QueryFlag(); _ExpandFormFeedSwitch = ExpandFormFeedArgument->QueryFlag(); _SqueezeBlanksSwitch = SqueezeBlanksArgument->QueryFlag(); _HelpSwitch = (BOOLEAN)(Help1Argument->QueryFlag() || Help2Argument->QueryFlag()); if ( StartAtLineArgument->IsValueSet() ) { _StartAtLine = StartAtLineArgument->QueryLong(); } if ( TabExpArgument->IsValueSet() ) { _TabExp = TabExpArgument->QueryLong(); } // // Clean up // DELETE( MoreVariableValue ); } DELETE( MoreVariableName ); } VOID MORE::GetArgumentsCmd( ) /*++ Routine Description: Obtains the arguments from the Command line Arguments: None. Return Value: None Notes: --*/ { ARRAY ArgArray; DSTRING CmdLine; PATH_ARGUMENT ProgramNameArgument; // // Prepare for parsing // if (// // Initialize the arguments // !(CmdLine.Initialize( GetCommandLine() )) || !(ArgArray.Initialize( 9, 9 )) || !(ProgramNameArgument.Initialize( "*" )) || !(ExtendedModeArgument->Initialize( "/E" )) || !(ClearScreenArgument->Initialize( "/C" )) || !(ExpandFormFeedArgument->Initialize( "/P" )) || !(SqueezeBlanksArgument->Initialize( "/S" )) || !(Help1Argument->Initialize( "/?" )) || !(Help2Argument->Initialize( "/H" )) || !(StartAtLineArgument->Initialize( "+*" )) || !(TabExpArgument->Initialize( "/t*" )) || ((_FilesArgument = NEW MULTIPLE_PATH_ARGUMENT) == NULL) || !(_FilesArgument->Initialize( "*", TRUE, TRUE )) || // // Put the arguments in the argument array // !(ArgArray.Put( &ProgramNameArgument )) || !(ArgArray.Put( ExtendedModeArgument )) || !(ArgArray.Put( ClearScreenArgument )) || !(ArgArray.Put( ExpandFormFeedArgument )) || !(ArgArray.Put( SqueezeBlanksArgument )) || !(ArgArray.Put( Help1Argument )) || !(ArgArray.Put( Help2Argument )) || !(ArgArray.Put( StartAtLineArgument )) || !(ArgArray.Put( TabExpArgument )) || !(ArgArray.Put( _FilesArgument )) ) { Fatal(); } // // Parse the arguments // ParseArguments( &CmdLine, &ArgArray ); // // Set the global structures // _ExtendedModeSwitch |= ExtendedModeArgument->QueryFlag(); _ClearScreenSwitch |= ClearScreenArgument->QueryFlag(); _ExpandFormFeedSwitch |= ExpandFormFeedArgument->QueryFlag(); _SqueezeBlanksSwitch |= SqueezeBlanksArgument->QueryFlag(); _HelpSwitch |= Help1Argument->QueryFlag() || Help2Argument->QueryFlag(); if ( StartAtLineArgument->IsValueSet() ) { _StartAtLine = StartAtLineArgument->QueryLong(); } if ( TabExpArgument->IsValueSet() ) { _TabExp = TabExpArgument->QueryLong(); } } VOID MORE::ParseArguments( IN PWSTRING CmdLine, OUT PARRAY ArgArray ) /*++ Routine Description: Parses a group of arguments Arguments: CmdLine - Supplies pointer to a command line to parse ArgArray - Supplies pointer to array of arguments Return Value: none Notes: --*/ { ARGUMENT_LEXEMIZER ArgLex; ARRAY LexArray; PWSTRING InvalidParameter; // // Initialize lexeme array and the lexemizer. // if ( !(LexArray.Initialize( 8, 8 )) || !(ArgLex.Initialize( &LexArray )) ) { Fatal(); } // // Set our parsing preferences // ArgLex.PutMultipleSwitch( "/ECPSH?" ); ArgLex.PutSwitches( "/" ); ArgLex.PutSeparators( " /\t" ); ArgLex.SetCaseSensitive( FALSE ); ArgLex.PutStartQuotes( "\"" ); ArgLex.PutEndQuotes( "\"" ); // // Parse the arguments // if ( !(ArgLex.PrepareToParse( CmdLine ))) { Fatal( EXIT_ERROR, MORE_ERROR_GENERAL, "" ); } if ( !ArgLex.DoParsing( ArgArray ) ) { _Message.Set(MSG_INVALID_PARAMETER); _Message.Display("%W", InvalidParameter = ArgLex.QueryInvalidArgument() ); DELETE(InvalidParameter); ExitProcess( 0 ); } LexArray.DeleteAllMembers( ); } VOID MORE::CheckArgumentConsistency ( ) /*++ Routine Description: Checks the consistency of the arguments Arguments: none Return Value: none Notes: --*/ { BOOLEAN ExtendedSwitches; if ( _HelpSwitch ) { // // Help wanted // Usage(); } ExtendedSwitches = (BOOLEAN)( _ClearScreenSwitch || _ExpandFormFeedSwitch || _SqueezeBlanksSwitch || TabExpArgument->IsValueSet() || ( _StartAtLine > (LONG)0 ) || _FilesArgument->WildCardExpansionFailed() || ( _FilesArgument->QueryPathCount() > (ULONG)0)); // // If the "extended" flag was not specified, then no other argument // is allowed. // if ( !_ExtendedModeSwitch && ExtendedSwitches ) { Fatal( EXIT_ERROR, MORE_ERROR_TOO_MANY_ARGUMENTS, "" ); } // // Error out if invalid file specified // if ( _FilesArgument->WildCardExpansionFailed() ) { Fatal( EXIT_ERROR, MORE_ERROR_CANNOT_ACCESS, "%W", _FilesArgument->GetLexemeThatFailed() ); } } VOID MORE::GetRegistryInfo( ) { ULONG valueType; DWORD value; ULONG valueLength = sizeof(value); HKEY key; LONG status; if (_ExtendedModeSwitch) return; status = RegOpenKeyEx(HKEY_CURRENT_USER, COMMAND_PROCESSOR_KEY, 0, KEY_READ, &key); if (status != ERROR_SUCCESS) { return; } status = RegQueryValueEx(key, ENABLE_EXTENSIONS_VALUE, NULL, &valueType, (LPBYTE)&value, &valueLength); if (status != ERROR_SUCCESS || valueType != REG_DWORD || valueLength != sizeof(DWORD)) { return; } _ExtendedModeSwitch = (BOOLEAN)value; }