windows-nt/Source/XPSP1/NT/base/fs/utils/more/argument.cxx

512 lines
12 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}