//+------------------------------------------------------------------ // // File: cbasecmd.cxx // // Contents: implementation for CBaseCmdlineObj // // Synoposis: CBaseCmdlineObj encapsulates a single command line // switch, eg. /username:lizch. It specifies the switch // string (username) and stores the value (lizch) as // a string. This class also provides methods for // retrieving the value, displaying it and setting it // to a default, and displaying usage for this switch. // // Classes: CBaseCmdlineObj // // Functions: // // History: 12/27/91 Lizch Created // 04/17/92 Lizch Converted to NLS_STR // 28 Aug 92 GeordiS changed nlsNULL to nlsNULLSTR // 31 Aug 92 GeordiS changed nlsNULLSTR back. // 09/09/92 Lizch Changed SUCCESS and NERR_Success // to NO_ERROR // 09/18/92 Lizch Precompile headers // 11/14/92 DwightKr Updates for new version of NLS_STR // 10/13/93 DeanE Converted to WCHAR // //------------------------------------------------------------------- #include #pragma hdrstop #include // public cmdlinew stuff #include "_clw.hxx" // private cmdlinew stuff #include // is functions LPCNSTR nszCmdlineBase = _TEXTN("Takes a string "); LPCNSTR nszLineArgBase = _TEXTN(" "); //+------------------------------------------------------------------ // // Function: CBaseCmdlineObj Constructor (1 of 2) // // Member: CBaseCmdlineObj // // Synoposis: Initialises switch string, usage values and whether the // switch is mandatory. This constructor gives no default value // for this switch. // // Arguments: [nszSwitch] - the expected switch string // [nszUsage] - the usage statement to display // [fMustHave] - whether the switch is mandatory or not. // if it is, an error will be generated if // the switch is not specified on the // command line. Defaults to FALSE. // [nszLineArg] - line arg // // Returns: none, but sets _iLastError // // History: Created 04/17/92 Lizch // //------------------------------------------------------------------- CBaseCmdlineObj::CBaseCmdlineObj( LPCNSTR nszSwitch, LPCNSTR nszUsage, BOOL fMustHave, LPCNSTR nszLineArg) { Init(nszSwitch, nszUsage, fMustHave, _TEXTN(""), nszLineArg); } //+------------------------------------------------------------------ // // Function: CBaseCmdlineObj Constructor (2 of 2) // // Member: CBaseCmdlineObj // // Synoposis: Initialises switch string, usage strings and default value. // This constructor is only used if a switch is optional. // // Effects: Sets fMandatory to FALSE (ie. switch is optional) // // Arguments: [nszSwitch] - the expected switch string // [nszUsage] - the usage statement to display // [nszDefault] - the value to be used if no switch is // specified on the command line. // [nszLineArg] - line arg // // Returns: none, but sets _iLastError // // History: Created 04/17/92 Lizch // //------------------------------------------------------------------- CBaseCmdlineObj::CBaseCmdlineObj( LPCNSTR nszSwitch, LPCNSTR nszUsage, LPCNSTR nszDefault, LPCNSTR nszLineArg) { Init(nszSwitch, nszUsage, FALSE, nszDefault, nszLineArg); _fDefaultSpecified = TRUE; } //+------------------------------------------------------------------ // // Function: Init // // Member: Private, called from constructors for CBaseCmdlineObj // // Synoposis: Sets defaults for members and allocates memory // for switch string. // // Arguments: [nszSwitch] - the expected command line switch // [nszUsage] - the usage statement for display // [fMustHave] - whether the switch is mandatory or not. // if it is, an error will be generated if // the switch is not specified on the // command line. Defaults to FALse // [nszDefault] - the value to be used if no switch is // specified on the command line. // [nszLineArg] - line arg. // // Returns: Nothing // // Modifies: Out of memory error, or CMDLINE_NO_ERROR // // History: 12/29/91 Lizch Created. // 04/17/92 Lizch Converted to NLS_STR // 7/14/92 DeanE Initialized _fFoundSwitch // 07/31/92 Davey Added _fSecondArg and _pnlsLineArgType, // and added nlsLineArg parameter. // //------------------------------------------------------------------- void CBaseCmdlineObj::Init( LPCNSTR nszSwitch, LPCNSTR nszUsage, BOOL fMustHave, LPCNSTR nszDefault, LPCNSTR nszLineArg) { SetError(CMDLINE_NO_ERROR); // Initialize member variables _pValue = NULL; _fMandatory = fMustHave; _fDefaultSpecified = FALSE; _fSecondArg = TRUE; _fFoundSwitch = FALSE; SetSeparator(nchDefaultSep); SetEquater(nchDefaultEquater); // Allocate space and initialize member strings _pnszUsageString = new NCHAR[_ncslen(nszUsage)+1]; if (_pnszUsageString == NULL) { SetError(CMDLINE_ERROR_OUT_OF_MEMORY); } else { _ncscpy(_pnszUsageString, nszUsage); } _pnszSwitch = new NCHAR[_ncslen(nszSwitch)+1]; if (_pnszSwitch == NULL) { SetError(CMDLINE_ERROR_OUT_OF_MEMORY); } else { _ncscpy(_pnszSwitch, nszSwitch); } _pnszDefaultValue = new NCHAR[_ncslen(nszDefault)+1]; if (NULL == _pnszDefaultValue) { SetError(CMDLINE_ERROR_OUT_OF_MEMORY); } else { _ncscpy(_pnszDefaultValue, nszDefault); } // if the passed in linearg is NULL then use default one, use // NULL to keep arguments consistent in parameter lists. // if (nszLineArg == NULL) { _pnszLineArgType = NULL; } else { _pnszLineArgType = new NCHAR[_ncslen(nszLineArg)+1]; if (NULL == _pnszLineArgType) { SetError(CMDLINE_ERROR_OUT_OF_MEMORY); } else { _ncscpy(_pnszLineArgType, nszLineArg); } } } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj destructor // // Synoposis: Frees any memory associated with the object // // History: 12/27/91 Lizch Created. // 04/17/92 Lizch Changed to NLS_STR. // 08/03/92 Davey Added delete of _pnlsLineArgType // //------------------------------------------------------------------- CBaseCmdlineObj::~CBaseCmdlineObj() { delete (NCHAR *)_pValue; _pValue = NULL; delete _pnszUsageString; delete _pnszSwitch; delete _pnszDefaultValue; delete _pnszLineArgType; } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::SetValue, public // // Synopsis: Stores the value specified after the switch string // (eg: "lizch" from "/username:lizch"). // // Arguments: [nszArg] - the string following the switch on // the command line. Excludes the // equator (eg. ':' in the above example) // // Returns: CMDLINE_NO_ERROR or out of memory // // History: 12/27/91 Lizch Created // 04/17/92 Lizch Converted to NLS_STR // //------------------------------------------------------------------- INT CBaseCmdlineObj::SetValue(LPCNSTR nszArg) { INT nRet = CMDLINE_NO_ERROR; // delete any existing pValue delete (NCHAR *)_pValue; _pValue = NULL; _pValue = new NCHAR[_ncslen(nszArg)+1]; if (_pValue == NULL) { nRet = CMDLINE_ERROR_OUT_OF_MEMORY; } else { _ncscpy((NCHAR *)_pValue, nszArg); } return(nRet); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::ResetValue, public // // Synopsis: Deletes the value so the object becomes "clean" again. // // // Returns: CMDLINE_NO_ERROR or out of memory // // History: 06/13/97 MariusB Created // //------------------------------------------------------------------- void CBaseCmdlineObj::ResetValue() { if (NULL != _pValue) { delete _pValue; _pValue = NULL; } } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::SetValueToDefault, public // // Synopsis: Sets the default value for the switch. This value is // used if no switch is specified on the command line. // // Effects: This is the base implementation for the virtual // method SetValueToDefault. It simply calls SetValue. // Derived classes may need to do more complex things, // eg, the default may be the name of the Domain Controller, // // Arguments: none // // Returns: CMDLINE_NO_ERROR or out of memory // // History: Created 12/27/91 Lizch // Converted to NLS_STR 04/17/92 Lizch // //------------------------------------------------------------------- INT CBaseCmdlineObj::SetValueToDefault() { return(SetValue(_pnszDefaultValue)); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::GetValue, public // // Synopsis: Returns a pointer to the switch value // // Arguments: none // // Returns: a const CHAR pointer to the switch value, not including // the equater character // // History: Created 05/27/92 Lizch // //------------------------------------------------------------------- LPCNSTR CBaseCmdlineObj::GetValue() { return((LPCNSTR)_pValue); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::IsFound, public // // Synopsis: Indicates whether this command line switch was found. // // Arguments: none // // Returns: TRUE if the switch was found, FALSE otherwise // // History: Created 05/27/92 Lizch // //------------------------------------------------------------------- BOOL CBaseCmdlineObj::IsFound() { return(_fFoundSwitch); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::SetFoundFlag, public // // Synopsis: Sets whether this command line switch was found. // // Arguments: TRUE if switch is found, FALSE otherwise // // Returns: nothing // // History: Created 05/27/92 Lizch // //------------------------------------------------------------------- void CBaseCmdlineObj::SetFoundFlag(BOOL fFound) { _fFoundSwitch = fFound; } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::IsRequired, public // // Synopsis: Indicates whether this command line switch is mandatory. // // Arguments: none // // Returns: TRUE if the switch was manadatory, FALSE otherwise // // History: Created 05/27/92 Lizch // //------------------------------------------------------------------- BOOL CBaseCmdlineObj::IsRequired () { return(_fMandatory); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::IsDefaultSpecified, public // // Synopsis: Indicates whether this command line switch has a default // value. // // Arguments: none // // Returns: TRUE if the switch has a default, FALSE otherwise // // History: Created 05/27/92 Lizch // //------------------------------------------------------------------- BOOL CBaseCmdlineObj::IsDefaultSpecified () { return(_fDefaultSpecified); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::SetSeparator, public // // Synoposis: Sets the valid switch separator character, i.e. // the '/' in /a:foo // // Arguments: [nchSeparator] - the new separator character // // Returns: Previous separator. // // History: 05/23/91 Lizch Created. // 08/10/92 Davey Changed to take only one char., added // return of error code // //------------------------------------------------------------------- NCHAR CBaseCmdlineObj::SetSeparator(NCHAR nchSeparator) { NCHAR nchOld = _nchSeparator; _nchSeparator = nchSeparator; return(nchOld); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::SetEquater, public // // Synoposis: Sets the set of valid equater characters, i.e. // the ':' in /a:foo // // Arguments: [nchEquater] - the new equater character // // Returns: Previous equater. // // History: 05/23/91 Lizch Created. // 08/10/92 Davey Changed to take only one char., added // return of error code // //------------------------------------------------------------------- NCHAR CBaseCmdlineObj::SetEquater(NCHAR nchEquater) { NCHAR nchOld = _nchEquater; _nchEquater = nchEquater; return(nchOld); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::GetSeparator, public // // Synoposis: Returns the separator character for this object. // // Arguments: None // // Returns: Current separator character. // // History: 10/17/93 DeanE Created // //------------------------------------------------------------------- NCHAR CBaseCmdlineObj::GetSeparator() { return(_nchSeparator); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::GetEquater, public // // Synoposis: Returns the equater character for this object. // // Arguments: None // // Returns: Current equater character. // // History: 10/17/93 DeanE Created // //------------------------------------------------------------------- NCHAR CBaseCmdlineObj::GetEquater() { return(_nchEquater); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::QuerySwitchString, public // // Synopsis: Returns a pointer to the switch string, eg. the "mc" in // /mc:foo // // Arguments: none // // Returns: a const NCHAR pointer to the switch string // // History: Created 05/27/92 Lizch // //------------------------------------------------------------------- LPCNSTR CBaseCmdlineObj::QuerySwitchString() { return(_pnszSwitch); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::DisplayValue, public // // Synoposis: Prints the stored command line value according to // current display method. Generally this will be to stdout. // // History: Created 12/27/91 Lizch // Converted to NLS_STR 04/17/92 Lizch // //------------------------------------------------------------------- void CBaseCmdlineObj::DisplayValue() { if (_pValue != NULL) { _sNprintf(_nszErrorBuf, _TEXTN("Command line switch %s has value %s\n"), _pnszSwitch, (NCHAR *)_pValue); (*_pfnDisplay)(_nszErrorBuf); } else { DisplayNoValue(); } } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::DisplayNoValue, protected // // Synoposis: Displays a "no value set" message. // // History: Created 05/14/92 Lizch // //------------------------------------------------------------------- void CBaseCmdlineObj::DisplayNoValue() { _sNprintf(_nszErrorBuf, _TEXTN("No value for command line switch %s\n"), _pnszSwitch); (*_pfnDisplay)(_nszErrorBuf); } //+------------------------------------------------------------------ // // Member: CBaseCmdlineObj::DisplaySpecialUsage, protected // // Synoposis: Outputs special usage - for base class there is none. // // History: Created 05/14/92 Lizch // //------------------------------------------------------------------- INT CBaseCmdlineObj::DisplaySpecialUsage( USHORT usDisplayWidth, USHORT usIndent, USHORT *pusWidth) { return(CMDLINE_NO_ERROR); } //+------------------------------------------------------------------- // // Method: CBaseCmdLineObj::QueryCmdlineType, protected, const // // Synoposis: returns a character pointer to the cmdline type. // // Arguments: None. // // Returns: const NCHAR * reference to string. // // History: 28-Jul-92 davey Created. // //-------------------------------------------------------------------- LPCNSTR CBaseCmdlineObj::QueryCmdlineType() const { return(nszCmdlineBase); } //+------------------------------------------------------------------- // // Method: CBaseCmdLineObj::QueryLineArgType, protected, const // // Synoposis: returns a character pointer to the line arg type. // // Arguments: None. // // Returns: const NCHAR *reference to string. // // History: 28-Jul-92 davey Created. // //-------------------------------------------------------------------- LPCNSTR CBaseCmdlineObj::QueryLineArgType() const { // if user has not defined one then give default one if (_pnszLineArgType == NULL) { return(nszLineArgBase); } else { return(_pnszLineArgType); } } //+------------------------------------------------------------------- // // Method: CBaseCmdLineObj::DisplayUsageLine, protected // // Synopsis: Displays line usage information // // Arguments: [pusWidth] - How much space is left on line to display // the usage. // [usDisplayWidth] - Max width allowed to display usage // [usIndent] - Amount to indent for next line of usage // // History: 28-Jul-92 davey Created. // // Notes: Looks like: // // test2 /mc: [/ml:] [/mt:] // [/mn:] [/mp:] [/mo:] // [/md:] [/?] // //-------------------------------------------------------------------- INT CBaseCmdlineObj::DisplayUsageLine( USHORT *pusWidth, USHORT usDisplayWidth, USHORT usIndent) { INT nRet = CMDLINE_NO_ERROR; LPNSTR pnszLine = NULL; ULONG cchLine; LPCNSTR nszLeftBracket = _TEXTN("["); LPCNSTR nszRightBracket = _TEXTN("]"); LPCNSTR nszType = QueryLineArgType(); NCHAR nszSeparator[2]; NCHAR nszEquater[2]; // Initialize separator and equater strings nszSeparator[0] = _nchSeparator; nszSeparator[1] = nchClNull; nszEquater[0] = _nchEquater; nszEquater[1] = nchClNull; // Determine length of the display line - Add one for terminating NULL cchLine = 1 + _ncslen(nszSeparator) + _ncslen(_pnszSwitch); if (FALSE == _fMandatory) { cchLine += _ncslen(nszLeftBracket) + _ncslen(nszRightBracket); } if (TRUE == _fSecondArg) { cchLine += _ncslen(nszEquater) + _ncslen(nszType); } // Build the display line pnszLine = new NCHAR[cchLine]; if (NULL == pnszLine) { return(CMDLINE_ERROR_OUT_OF_MEMORY); } *pnszLine = nchClNull; if (FALSE == _fMandatory) { _ncscat(pnszLine, nszLeftBracket); } _ncscat(pnszLine, nszSeparator); _ncscat(pnszLine, _pnszSwitch); if (TRUE == _fSecondArg) { _ncscat(pnszLine, nszEquater); _ncscat(pnszLine, nszType); } if (FALSE == _fMandatory) { _ncscat(pnszLine, nszRightBracket); } nRet = DisplayWord(pnszLine, usDisplayWidth, usIndent, pusWidth); // Clean up and exit delete pnszLine; return(nRet); } //+------------------------------------------------------------------- // // Method: CBaseCmdLineObj::DisplayUsageDescr, protected // // Synopsis: Displays switch descriptions information // // Arguments: [usSwitchIndent] - Amount to indent for switches // [usDisplayWidth] - Max width allowed to display usage // [usUsageIndent] - Amount to indent for next line of usage // // History: 28-Jul-92 davey Created. // // Notes: looks like. // // /mc Takes a list of strings specifying worker names. // These workers should have full names. // Don't you think so? // The strings in the list are separated by one of the following // character(s): ",; ". // /ml Takes a string specifying log server name. // /mt Takes a string specifying name of the test. // /mn Takes a string specifying email name of the tester. // /mp Takes a string specifying path name to log to. // /mo Takes a string specifying name of the object. // /md Takes a string specifying name of the dispatcher to use. // /? Flag specifying command line usage. It defaults to FALSE. // // Here's how the various indent values relate to each other: // // <-------------------------usDisplayWidth-------------------------> // <--usSwitchIndent-->/foo // <--------usUsageIndent----->Takes a list... // //-------------------------------------------------------------------- INT CBaseCmdlineObj::DisplayUsageDescr( USHORT usSwitchIndent, USHORT usDisplayWidth, USHORT usUsageIndent) { INT iRC; LPNSTR pnszSwitch; LPNSTR pnszUsage; LPNSTR pnszDefault = NULL; USHORT cchUsage; USHORT cchSwitch; USHORT cchPaddedSwitch; USHORT usLineSpaceLeft; LPCNSTR nszSpecify = _TEXTN("specifying "); LPCNSTR nszDefault = _TEXTN("It defaults to "); LPCNSTR nszType = QueryCmdlineType(); NCHAR nszSeparator[2]; // Initialize separator string nszSeparator[0] = _nchSeparator; nszSeparator[1] = nchClNull; // Calculate size of switch buffer - if this length is less than // usUsageIndent then allocate extra room to pad spaces out to // usUsageIndent and the usage will start on the same line; else // the usage will start on the next line with an indent. Also, // the null-terminator is NOT accounted for in this value. // cchSwitch = (USHORT) (usSwitchIndent + _ncslen(nszSeparator) + _ncslen(_pnszSwitch) ) ; if (cchSwitch < usUsageIndent) { cchPaddedSwitch = usUsageIndent; } else { cchPaddedSwitch = (USHORT) (cchSwitch + usUsageIndent + _ncslen(nszClNewLine) ); } // Calculate size of usage buffer - null-terminator NOT accounted for // cchUsage = (USHORT) (_ncslen(nszType) + _ncslen(nszSpecify) + _ncslen(_pnszUsageString) ); // Allocate buffers - add 1 for NULL-terminators pnszSwitch = new NCHAR[cchPaddedSwitch+1]; pnszUsage = new NCHAR[cchUsage+1]; if (pnszSwitch == NULL || pnszUsage == NULL) { delete pnszSwitch; delete pnszUsage; return(CMDLINE_ERROR_OUT_OF_MEMORY); } // Initialize switch buffer - fill with usSwitchIndent spaces, then // append the separator and switch, then pad with spaces out to // usUsageIndent if necessary // for (USHORT i=0; i= usUsageIndent) { // Pad a new line. _ncscat(pnszSwitch, nszClNewLine); } // Pad spaces until usUsageIndemt for (i = (USHORT) _ncslen(pnszSwitch); i < cchPaddedSwitch; i++) { pnszSwitch[i] = nchClSpace; } pnszSwitch[cchPaddedSwitch] = nchClNull; // Initialize usage buffer _ncscpy(pnszUsage, nszType); _ncscat(pnszUsage, nszSpecify); _ncscat(pnszUsage, _pnszUsageString); // Now we're ready to output the strings - output the switch, then // set up the values needed to output the usage line. // (*_pfnDisplay)(pnszSwitch); usLineSpaceLeft = (USHORT) (usDisplayWidth - usUsageIndent); // Output the usage iRC = DisplayStringByWords( pnszUsage, usDisplayWidth, usUsageIndent, &usLineSpaceLeft); if (iRC != CMDLINE_NO_ERROR) { delete pnszSwitch; delete pnszUsage; return(iRC); } // output the special usage // iRC = DisplaySpecialUsage(usDisplayWidth, usUsageIndent, &usLineSpaceLeft); if (iRC != CMDLINE_NO_ERROR) { delete pnszSwitch; delete pnszUsage; return(iRC); } // output the default value string // if (_fDefaultSpecified) { // Default string is " " + nszDefault + _pnszDefaultValue + "." pnszDefault = new NCHAR[_ncslen(_pnszDefaultValue) + _ncslen(nszDefault) + 4]; if (pnszDefault == NULL) { iRC = CMDLINE_ERROR_OUT_OF_MEMORY; } else { _ncscpy(pnszDefault, _TEXTN(" ")); _ncscat(pnszDefault, nszDefault); _ncscat(pnszDefault, _pnszDefaultValue); _ncscat(pnszDefault, _TEXTN(".")); iRC = DisplayStringByWords( pnszDefault, usDisplayWidth, usUsageIndent, &usLineSpaceLeft); } if (iRC != CMDLINE_NO_ERROR) { delete pnszDefault; delete pnszSwitch; delete pnszUsage; return(iRC); } } // Next thing output should go on a new line // (*_pfnDisplay)(nszClNewLine); delete pnszSwitch; delete pnszUsage; delete pnszDefault; return(iRC); } //+------------------------------------------------------------------- // // Method: CBaseCmdLineObj::DisplayStringByWords, protected // // Synopsis: Writes out the strings word by word following indentation // and display width rules; words are delimeted by spaces. // The string begins on the current line at the current // location (usDisplayWidth-*pusSpaceLeft), including // any leading space characters. // // Arguments: [nszString] - String to output. // [usDisplayWidth] - Max width allowed to display usage // [usIndent] - Amount to indent for next line of usage // [pusSpaceLeft] - Space left on this line // // History: 28-Jul-92 davey Created. // //-------------------------------------------------------------------- INT CBaseCmdlineObj::DisplayStringByWords( LPCNSTR nszString, USHORT usDisplayWidth, USHORT usIndent, USHORT *pusSpaceLeft) { INT iRC = CMDLINE_NO_ERROR; BOOL fDone = FALSE; LPNSTR pnszWord = NULL; LPCNSTR pnchWord = nszString; LPCNSTR pnchTrav = nszString; USHORT i; // Skip leading spaces, but they are part of the first word while (nchClSpace == *pnchTrav) { pnchTrav++; } // Traverse the string until we get to the end while (!fDone) { // Traverse until we find a space, newline, or null switch(*pnchTrav) { case L' ': // Retrieve the word from the string iRC = CopyWord(pnchWord, pnchTrav-pnchWord, &pnszWord); if (iRC == CMDLINE_NO_ERROR) { // Output the word iRC = DisplayWord( pnszWord, usDisplayWidth, usIndent, pusSpaceLeft); } delete pnszWord; //Set up the next word pnchWord = pnchTrav++; // traverse to next non-space character while (nchClSpace == *pnchTrav) { pnchTrav++; } break; case L'\n': // Retrieve the word from the string, including the newline iRC = CopyWord(pnchWord, ++pnchTrav-pnchWord, &pnszWord); if (iRC == CMDLINE_NO_ERROR) { // Output the word iRC = DisplayWord( pnszWord, usDisplayWidth, usIndent, pusSpaceLeft); } delete pnszWord; // Output usIndent spaces for (i=0; i