Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1179 lines
35 KiB

  1. //+------------------------------------------------------------------
  2. //
  3. // File: cbasecmd.cxx
  4. //
  5. // Contents: implementation for CBaseCmdlineObj
  6. //
  7. // Synoposis: CBaseCmdlineObj encapsulates a single command line
  8. // switch, eg. /username:lizch. It specifies the switch
  9. // string (username) and stores the value (lizch) as
  10. // a string. This class also provides methods for
  11. // retrieving the value, displaying it and setting it
  12. // to a default, and displaying usage for this switch.
  13. //
  14. // Classes: CBaseCmdlineObj
  15. //
  16. // Functions:
  17. //
  18. // History: 12/27/91 Lizch Created
  19. // 04/17/92 Lizch Converted to NLS_STR
  20. // 28 Aug 92 GeordiS changed nlsNULL to nlsNULLSTR
  21. // 31 Aug 92 GeordiS changed nlsNULLSTR back.
  22. // 09/09/92 Lizch Changed SUCCESS and NERR_Success
  23. // to NO_ERROR
  24. // 09/18/92 Lizch Precompile headers
  25. // 11/14/92 DwightKr Updates for new version of NLS_STR
  26. // 10/13/93 DeanE Converted to WCHAR
  27. //
  28. //-------------------------------------------------------------------
  29. #include <comtpch.hxx>
  30. #pragma hdrstop
  31. #include <cmdlinew.hxx> // public cmdlinew stuff
  32. #include "_clw.hxx" // private cmdlinew stuff
  33. #include <ctype.h> // is functions
  34. LPCNSTR nszCmdlineBase = _TEXTN("Takes a string ");
  35. LPCNSTR nszLineArgBase = _TEXTN("<string> ");
  36. //+------------------------------------------------------------------
  37. //
  38. // Function: CBaseCmdlineObj Constructor (1 of 2)
  39. //
  40. // Member: CBaseCmdlineObj
  41. //
  42. // Synoposis: Initialises switch string, usage values and whether the
  43. // switch is mandatory. This constructor gives no default value
  44. // for this switch.
  45. //
  46. // Arguments: [nszSwitch] - the expected switch string
  47. // [nszUsage] - the usage statement to display
  48. // [fMustHave] - whether the switch is mandatory or not.
  49. // if it is, an error will be generated if
  50. // the switch is not specified on the
  51. // command line. Defaults to FALSE.
  52. // [nszLineArg] - line arg
  53. //
  54. // Returns: none, but sets _iLastError
  55. //
  56. // History: Created 04/17/92 Lizch
  57. //
  58. //-------------------------------------------------------------------
  59. CBaseCmdlineObj::CBaseCmdlineObj(
  60. LPCNSTR nszSwitch,
  61. LPCNSTR nszUsage,
  62. BOOL fMustHave,
  63. LPCNSTR nszLineArg)
  64. {
  65. Init(nszSwitch, nszUsage, fMustHave, _TEXTN(""), nszLineArg);
  66. }
  67. //+------------------------------------------------------------------
  68. //
  69. // Function: CBaseCmdlineObj Constructor (2 of 2)
  70. //
  71. // Member: CBaseCmdlineObj
  72. //
  73. // Synoposis: Initialises switch string, usage strings and default value.
  74. // This constructor is only used if a switch is optional.
  75. //
  76. // Effects: Sets fMandatory to FALSE (ie. switch is optional)
  77. //
  78. // Arguments: [nszSwitch] - the expected switch string
  79. // [nszUsage] - the usage statement to display
  80. // [nszDefault] - the value to be used if no switch is
  81. // specified on the command line.
  82. // [nszLineArg] - line arg
  83. //
  84. // Returns: none, but sets _iLastError
  85. //
  86. // History: Created 04/17/92 Lizch
  87. //
  88. //-------------------------------------------------------------------
  89. CBaseCmdlineObj::CBaseCmdlineObj(
  90. LPCNSTR nszSwitch,
  91. LPCNSTR nszUsage,
  92. LPCNSTR nszDefault,
  93. LPCNSTR nszLineArg)
  94. {
  95. Init(nszSwitch, nszUsage, FALSE, nszDefault, nszLineArg);
  96. _fDefaultSpecified = TRUE;
  97. }
  98. //+------------------------------------------------------------------
  99. //
  100. // Function: Init
  101. //
  102. // Member: Private, called from constructors for CBaseCmdlineObj
  103. //
  104. // Synoposis: Sets defaults for members and allocates memory
  105. // for switch string.
  106. //
  107. // Arguments: [nszSwitch] - the expected command line switch
  108. // [nszUsage] - the usage statement for display
  109. // [fMustHave] - whether the switch is mandatory or not.
  110. // if it is, an error will be generated if
  111. // the switch is not specified on the
  112. // command line. Defaults to FALse
  113. // [nszDefault] - the value to be used if no switch is
  114. // specified on the command line.
  115. // [nszLineArg] - line arg.
  116. //
  117. // Returns: Nothing
  118. //
  119. // Modifies: Out of memory error, or CMDLINE_NO_ERROR
  120. //
  121. // History: 12/29/91 Lizch Created.
  122. // 04/17/92 Lizch Converted to NLS_STR
  123. // 7/14/92 DeanE Initialized _fFoundSwitch
  124. // 07/31/92 Davey Added _fSecondArg and _pnlsLineArgType,
  125. // and added nlsLineArg parameter.
  126. //
  127. //-------------------------------------------------------------------
  128. void CBaseCmdlineObj::Init(
  129. LPCNSTR nszSwitch,
  130. LPCNSTR nszUsage,
  131. BOOL fMustHave,
  132. LPCNSTR nszDefault,
  133. LPCNSTR nszLineArg)
  134. {
  135. SetError(CMDLINE_NO_ERROR);
  136. // Initialize member variables
  137. _pValue = NULL;
  138. _fMandatory = fMustHave;
  139. _fDefaultSpecified = FALSE;
  140. _fSecondArg = TRUE;
  141. _fFoundSwitch = FALSE;
  142. SetSeparator(nchDefaultSep);
  143. SetEquater(nchDefaultEquater);
  144. // Allocate space and initialize member strings
  145. _pnszUsageString = new NCHAR[_ncslen(nszUsage)+1];
  146. if (_pnszUsageString == NULL)
  147. {
  148. SetError(CMDLINE_ERROR_OUT_OF_MEMORY);
  149. }
  150. else
  151. {
  152. _ncscpy(_pnszUsageString, nszUsage);
  153. }
  154. _pnszSwitch = new NCHAR[_ncslen(nszSwitch)+1];
  155. if (_pnszSwitch == NULL)
  156. {
  157. SetError(CMDLINE_ERROR_OUT_OF_MEMORY);
  158. }
  159. else
  160. {
  161. _ncscpy(_pnszSwitch, nszSwitch);
  162. }
  163. _pnszDefaultValue = new NCHAR[_ncslen(nszDefault)+1];
  164. if (NULL == _pnszDefaultValue)
  165. {
  166. SetError(CMDLINE_ERROR_OUT_OF_MEMORY);
  167. }
  168. else
  169. {
  170. _ncscpy(_pnszDefaultValue, nszDefault);
  171. }
  172. // if the passed in linearg is NULL then use default one, use
  173. // NULL to keep arguments consistent in parameter lists.
  174. //
  175. if (nszLineArg == NULL)
  176. {
  177. _pnszLineArgType = NULL;
  178. }
  179. else
  180. {
  181. _pnszLineArgType = new NCHAR[_ncslen(nszLineArg)+1];
  182. if (NULL == _pnszLineArgType)
  183. {
  184. SetError(CMDLINE_ERROR_OUT_OF_MEMORY);
  185. }
  186. else
  187. {
  188. _ncscpy(_pnszLineArgType, nszLineArg);
  189. }
  190. }
  191. }
  192. //+------------------------------------------------------------------
  193. //
  194. // Member: CBaseCmdlineObj destructor
  195. //
  196. // Synoposis: Frees any memory associated with the object
  197. //
  198. // History: 12/27/91 Lizch Created.
  199. // 04/17/92 Lizch Changed to NLS_STR.
  200. // 08/03/92 Davey Added delete of _pnlsLineArgType
  201. //
  202. //-------------------------------------------------------------------
  203. CBaseCmdlineObj::~CBaseCmdlineObj()
  204. {
  205. delete (NCHAR *)_pValue;
  206. _pValue = NULL;
  207. delete _pnszUsageString;
  208. delete _pnszSwitch;
  209. delete _pnszDefaultValue;
  210. delete _pnszLineArgType;
  211. }
  212. //+------------------------------------------------------------------
  213. //
  214. // Member: CBaseCmdlineObj::SetValue, public
  215. //
  216. // Synopsis: Stores the value specified after the switch string
  217. // (eg: "lizch" from "/username:lizch").
  218. //
  219. // Arguments: [nszArg] - the string following the switch on
  220. // the command line. Excludes the
  221. // equator (eg. ':' in the above example)
  222. //
  223. // Returns: CMDLINE_NO_ERROR or out of memory
  224. //
  225. // History: 12/27/91 Lizch Created
  226. // 04/17/92 Lizch Converted to NLS_STR
  227. //
  228. //-------------------------------------------------------------------
  229. INT CBaseCmdlineObj::SetValue(LPCNSTR nszArg)
  230. {
  231. INT nRet = CMDLINE_NO_ERROR;
  232. // delete any existing pValue
  233. delete (NCHAR *)_pValue;
  234. _pValue = NULL;
  235. _pValue = new NCHAR[_ncslen(nszArg)+1];
  236. if (_pValue == NULL)
  237. {
  238. nRet = CMDLINE_ERROR_OUT_OF_MEMORY;
  239. }
  240. else
  241. {
  242. _ncscpy((NCHAR *)_pValue, nszArg);
  243. }
  244. return(nRet);
  245. }
  246. //+------------------------------------------------------------------
  247. //
  248. // Member: CBaseCmdlineObj::ResetValue, public
  249. //
  250. // Synopsis: Deletes the value so the object becomes "clean" again.
  251. //
  252. //
  253. // Returns: CMDLINE_NO_ERROR or out of memory
  254. //
  255. // History: 06/13/97 MariusB Created
  256. //
  257. //-------------------------------------------------------------------
  258. void CBaseCmdlineObj::ResetValue()
  259. {
  260. if (NULL != _pValue)
  261. {
  262. delete _pValue;
  263. _pValue = NULL;
  264. }
  265. }
  266. //+------------------------------------------------------------------
  267. //
  268. // Member: CBaseCmdlineObj::SetValueToDefault, public
  269. //
  270. // Synopsis: Sets the default value for the switch. This value is
  271. // used if no switch is specified on the command line.
  272. //
  273. // Effects: This is the base implementation for the virtual
  274. // method SetValueToDefault. It simply calls SetValue.
  275. // Derived classes may need to do more complex things,
  276. // eg, the default may be the name of the Domain Controller,
  277. //
  278. // Arguments: none
  279. //
  280. // Returns: CMDLINE_NO_ERROR or out of memory
  281. //
  282. // History: Created 12/27/91 Lizch
  283. // Converted to NLS_STR 04/17/92 Lizch
  284. //
  285. //-------------------------------------------------------------------
  286. INT CBaseCmdlineObj::SetValueToDefault()
  287. {
  288. return(SetValue(_pnszDefaultValue));
  289. }
  290. //+------------------------------------------------------------------
  291. //
  292. // Member: CBaseCmdlineObj::GetValue, public
  293. //
  294. // Synopsis: Returns a pointer to the switch value
  295. //
  296. // Arguments: none
  297. //
  298. // Returns: a const CHAR pointer to the switch value, not including
  299. // the equater character
  300. //
  301. // History: Created 05/27/92 Lizch
  302. //
  303. //-------------------------------------------------------------------
  304. LPCNSTR CBaseCmdlineObj::GetValue()
  305. {
  306. return((LPCNSTR)_pValue);
  307. }
  308. //+------------------------------------------------------------------
  309. //
  310. // Member: CBaseCmdlineObj::IsFound, public
  311. //
  312. // Synopsis: Indicates whether this command line switch was found.
  313. //
  314. // Arguments: none
  315. //
  316. // Returns: TRUE if the switch was found, FALSE otherwise
  317. //
  318. // History: Created 05/27/92 Lizch
  319. //
  320. //-------------------------------------------------------------------
  321. BOOL CBaseCmdlineObj::IsFound()
  322. {
  323. return(_fFoundSwitch);
  324. }
  325. //+------------------------------------------------------------------
  326. //
  327. // Member: CBaseCmdlineObj::SetFoundFlag, public
  328. //
  329. // Synopsis: Sets whether this command line switch was found.
  330. //
  331. // Arguments: TRUE if switch is found, FALSE otherwise
  332. //
  333. // Returns: nothing
  334. //
  335. // History: Created 05/27/92 Lizch
  336. //
  337. //-------------------------------------------------------------------
  338. void CBaseCmdlineObj::SetFoundFlag(BOOL fFound)
  339. {
  340. _fFoundSwitch = fFound;
  341. }
  342. //+------------------------------------------------------------------
  343. //
  344. // Member: CBaseCmdlineObj::IsRequired, public
  345. //
  346. // Synopsis: Indicates whether this command line switch is mandatory.
  347. //
  348. // Arguments: none
  349. //
  350. // Returns: TRUE if the switch was manadatory, FALSE otherwise
  351. //
  352. // History: Created 05/27/92 Lizch
  353. //
  354. //-------------------------------------------------------------------
  355. BOOL CBaseCmdlineObj::IsRequired ()
  356. {
  357. return(_fMandatory);
  358. }
  359. //+------------------------------------------------------------------
  360. //
  361. // Member: CBaseCmdlineObj::IsDefaultSpecified, public
  362. //
  363. // Synopsis: Indicates whether this command line switch has a default
  364. // value.
  365. //
  366. // Arguments: none
  367. //
  368. // Returns: TRUE if the switch has a default, FALSE otherwise
  369. //
  370. // History: Created 05/27/92 Lizch
  371. //
  372. //-------------------------------------------------------------------
  373. BOOL CBaseCmdlineObj::IsDefaultSpecified ()
  374. {
  375. return(_fDefaultSpecified);
  376. }
  377. //+------------------------------------------------------------------
  378. //
  379. // Member: CBaseCmdlineObj::SetSeparator, public
  380. //
  381. // Synoposis: Sets the valid switch separator character, i.e.
  382. // the '/' in /a:foo
  383. //
  384. // Arguments: [nchSeparator] - the new separator character
  385. //
  386. // Returns: Previous separator.
  387. //
  388. // History: 05/23/91 Lizch Created.
  389. // 08/10/92 Davey Changed to take only one char., added
  390. // return of error code
  391. //
  392. //-------------------------------------------------------------------
  393. NCHAR CBaseCmdlineObj::SetSeparator(NCHAR nchSeparator)
  394. {
  395. NCHAR nchOld = _nchSeparator;
  396. _nchSeparator = nchSeparator;
  397. return(nchOld);
  398. }
  399. //+------------------------------------------------------------------
  400. //
  401. // Member: CBaseCmdlineObj::SetEquater, public
  402. //
  403. // Synoposis: Sets the set of valid equater characters, i.e.
  404. // the ':' in /a:foo
  405. //
  406. // Arguments: [nchEquater] - the new equater character
  407. //
  408. // Returns: Previous equater.
  409. //
  410. // History: 05/23/91 Lizch Created.
  411. // 08/10/92 Davey Changed to take only one char., added
  412. // return of error code
  413. //
  414. //-------------------------------------------------------------------
  415. NCHAR CBaseCmdlineObj::SetEquater(NCHAR nchEquater)
  416. {
  417. NCHAR nchOld = _nchEquater;
  418. _nchEquater = nchEquater;
  419. return(nchOld);
  420. }
  421. //+------------------------------------------------------------------
  422. //
  423. // Member: CBaseCmdlineObj::GetSeparator, public
  424. //
  425. // Synoposis: Returns the separator character for this object.
  426. //
  427. // Arguments: None
  428. //
  429. // Returns: Current separator character.
  430. //
  431. // History: 10/17/93 DeanE Created
  432. //
  433. //-------------------------------------------------------------------
  434. NCHAR CBaseCmdlineObj::GetSeparator()
  435. {
  436. return(_nchSeparator);
  437. }
  438. //+------------------------------------------------------------------
  439. //
  440. // Member: CBaseCmdlineObj::GetEquater, public
  441. //
  442. // Synoposis: Returns the equater character for this object.
  443. //
  444. // Arguments: None
  445. //
  446. // Returns: Current equater character.
  447. //
  448. // History: 10/17/93 DeanE Created
  449. //
  450. //-------------------------------------------------------------------
  451. NCHAR CBaseCmdlineObj::GetEquater()
  452. {
  453. return(_nchEquater);
  454. }
  455. //+------------------------------------------------------------------
  456. //
  457. // Member: CBaseCmdlineObj::QuerySwitchString, public
  458. //
  459. // Synopsis: Returns a pointer to the switch string, eg. the "mc" in
  460. // /mc:foo
  461. //
  462. // Arguments: none
  463. //
  464. // Returns: a const NCHAR pointer to the switch string
  465. //
  466. // History: Created 05/27/92 Lizch
  467. //
  468. //-------------------------------------------------------------------
  469. LPCNSTR CBaseCmdlineObj::QuerySwitchString()
  470. {
  471. return(_pnszSwitch);
  472. }
  473. //+------------------------------------------------------------------
  474. //
  475. // Member: CBaseCmdlineObj::DisplayValue, public
  476. //
  477. // Synoposis: Prints the stored command line value according to
  478. // current display method. Generally this will be to stdout.
  479. //
  480. // History: Created 12/27/91 Lizch
  481. // Converted to NLS_STR 04/17/92 Lizch
  482. //
  483. //-------------------------------------------------------------------
  484. void CBaseCmdlineObj::DisplayValue()
  485. {
  486. if (_pValue != NULL)
  487. {
  488. _sNprintf(_nszErrorBuf,
  489. _TEXTN("Command line switch %s has value %s\n"),
  490. _pnszSwitch,
  491. (NCHAR *)_pValue);
  492. (*_pfnDisplay)(_nszErrorBuf);
  493. }
  494. else
  495. {
  496. DisplayNoValue();
  497. }
  498. }
  499. //+------------------------------------------------------------------
  500. //
  501. // Member: CBaseCmdlineObj::DisplayNoValue, protected
  502. //
  503. // Synoposis: Displays a "no value set" message.
  504. //
  505. // History: Created 05/14/92 Lizch
  506. //
  507. //-------------------------------------------------------------------
  508. void CBaseCmdlineObj::DisplayNoValue()
  509. {
  510. _sNprintf(_nszErrorBuf,
  511. _TEXTN("No value for command line switch %s\n"),
  512. _pnszSwitch);
  513. (*_pfnDisplay)(_nszErrorBuf);
  514. }
  515. //+------------------------------------------------------------------
  516. //
  517. // Member: CBaseCmdlineObj::DisplaySpecialUsage, protected
  518. //
  519. // Synoposis: Outputs special usage - for base class there is none.
  520. //
  521. // History: Created 05/14/92 Lizch
  522. //
  523. //-------------------------------------------------------------------
  524. INT CBaseCmdlineObj::DisplaySpecialUsage(
  525. USHORT usDisplayWidth,
  526. USHORT usIndent,
  527. USHORT *pusWidth)
  528. {
  529. return(CMDLINE_NO_ERROR);
  530. }
  531. //+-------------------------------------------------------------------
  532. //
  533. // Method: CBaseCmdLineObj::QueryCmdlineType, protected, const
  534. //
  535. // Synoposis: returns a character pointer to the cmdline type.
  536. //
  537. // Arguments: None.
  538. //
  539. // Returns: const NCHAR * reference to string.
  540. //
  541. // History: 28-Jul-92 davey Created.
  542. //
  543. //--------------------------------------------------------------------
  544. LPCNSTR CBaseCmdlineObj::QueryCmdlineType() const
  545. {
  546. return(nszCmdlineBase);
  547. }
  548. //+-------------------------------------------------------------------
  549. //
  550. // Method: CBaseCmdLineObj::QueryLineArgType, protected, const
  551. //
  552. // Synoposis: returns a character pointer to the line arg type.
  553. //
  554. // Arguments: None.
  555. //
  556. // Returns: const NCHAR *reference to string.
  557. //
  558. // History: 28-Jul-92 davey Created.
  559. //
  560. //--------------------------------------------------------------------
  561. LPCNSTR CBaseCmdlineObj::QueryLineArgType() const
  562. {
  563. // if user has not defined one then give default one
  564. if (_pnszLineArgType == NULL)
  565. {
  566. return(nszLineArgBase);
  567. }
  568. else
  569. {
  570. return(_pnszLineArgType);
  571. }
  572. }
  573. //+-------------------------------------------------------------------
  574. //
  575. // Method: CBaseCmdLineObj::DisplayUsageLine, protected
  576. //
  577. // Synopsis: Displays line usage information
  578. //
  579. // Arguments: [pusWidth] - How much space is left on line to display
  580. // the usage.
  581. // [usDisplayWidth] - Max width allowed to display usage
  582. // [usIndent] - Amount to indent for next line of usage
  583. //
  584. // History: 28-Jul-92 davey Created.
  585. //
  586. // Notes: Looks like:
  587. //
  588. // test2 /mc:<worker> [/ml:<log_server>] [/mt:<test>]
  589. // [/mn:<tester-email>] [/mp:<path>] [/mo:<obj_name>]
  590. // [/md:<dispatcher>] [/?]
  591. //
  592. //--------------------------------------------------------------------
  593. INT CBaseCmdlineObj::DisplayUsageLine(
  594. USHORT *pusWidth,
  595. USHORT usDisplayWidth,
  596. USHORT usIndent)
  597. {
  598. INT nRet = CMDLINE_NO_ERROR;
  599. LPNSTR pnszLine = NULL;
  600. ULONG cchLine;
  601. LPCNSTR nszLeftBracket = _TEXTN("[");
  602. LPCNSTR nszRightBracket = _TEXTN("]");
  603. LPCNSTR nszType = QueryLineArgType();
  604. NCHAR nszSeparator[2];
  605. NCHAR nszEquater[2];
  606. // Initialize separator and equater strings
  607. nszSeparator[0] = _nchSeparator;
  608. nszSeparator[1] = nchClNull;
  609. nszEquater[0] = _nchEquater;
  610. nszEquater[1] = nchClNull;
  611. // Determine length of the display line - Add one for terminating NULL
  612. cchLine = 1 + _ncslen(nszSeparator) + _ncslen(_pnszSwitch);
  613. if (FALSE == _fMandatory)
  614. {
  615. cchLine += _ncslen(nszLeftBracket) + _ncslen(nszRightBracket);
  616. }
  617. if (TRUE == _fSecondArg)
  618. {
  619. cchLine += _ncslen(nszEquater) + _ncslen(nszType);
  620. }
  621. // Build the display line
  622. pnszLine = new NCHAR[cchLine];
  623. if (NULL == pnszLine)
  624. {
  625. return(CMDLINE_ERROR_OUT_OF_MEMORY);
  626. }
  627. *pnszLine = nchClNull;
  628. if (FALSE == _fMandatory)
  629. {
  630. _ncscat(pnszLine, nszLeftBracket);
  631. }
  632. _ncscat(pnszLine, nszSeparator);
  633. _ncscat(pnszLine, _pnszSwitch);
  634. if (TRUE == _fSecondArg)
  635. {
  636. _ncscat(pnszLine, nszEquater);
  637. _ncscat(pnszLine, nszType);
  638. }
  639. if (FALSE == _fMandatory)
  640. {
  641. _ncscat(pnszLine, nszRightBracket);
  642. }
  643. nRet = DisplayWord(pnszLine, usDisplayWidth, usIndent, pusWidth);
  644. // Clean up and exit
  645. delete pnszLine;
  646. return(nRet);
  647. }
  648. //+-------------------------------------------------------------------
  649. //
  650. // Method: CBaseCmdLineObj::DisplayUsageDescr, protected
  651. //
  652. // Synopsis: Displays switch descriptions information
  653. //
  654. // Arguments: [usSwitchIndent] - Amount to indent for switches
  655. // [usDisplayWidth] - Max width allowed to display usage
  656. // [usUsageIndent] - Amount to indent for next line of usage
  657. //
  658. // History: 28-Jul-92 davey Created.
  659. //
  660. // Notes: looks like.
  661. //
  662. // /mc Takes a list of strings specifying worker names.
  663. // These workers should have full names.
  664. // Don't you think so?
  665. // The strings in the list are separated by one of the following
  666. // character(s): ",; ".
  667. // /ml Takes a string specifying log server name.
  668. // /mt Takes a string specifying name of the test.
  669. // /mn Takes a string specifying email name of the tester.
  670. // /mp Takes a string specifying path name to log to.
  671. // /mo Takes a string specifying name of the object.
  672. // /md Takes a string specifying name of the dispatcher to use.
  673. // /? Flag specifying command line usage. It defaults to FALSE.
  674. //
  675. // Here's how the various indent values relate to each other:
  676. //
  677. // <-------------------------usDisplayWidth------------------------->
  678. // <--usSwitchIndent-->/foo
  679. // <--------usUsageIndent----->Takes a list...
  680. //
  681. //--------------------------------------------------------------------
  682. INT CBaseCmdlineObj::DisplayUsageDescr(
  683. USHORT usSwitchIndent,
  684. USHORT usDisplayWidth,
  685. USHORT usUsageIndent)
  686. {
  687. INT iRC;
  688. LPNSTR pnszSwitch;
  689. LPNSTR pnszUsage;
  690. LPNSTR pnszDefault = NULL;
  691. USHORT cchUsage;
  692. USHORT cchSwitch;
  693. USHORT cchPaddedSwitch;
  694. USHORT usLineSpaceLeft;
  695. LPCNSTR nszSpecify = _TEXTN("specifying ");
  696. LPCNSTR nszDefault = _TEXTN("It defaults to ");
  697. LPCNSTR nszType = QueryCmdlineType();
  698. NCHAR nszSeparator[2];
  699. // Initialize separator string
  700. nszSeparator[0] = _nchSeparator;
  701. nszSeparator[1] = nchClNull;
  702. // Calculate size of switch buffer - if this length is less than
  703. // usUsageIndent then allocate extra room to pad spaces out to
  704. // usUsageIndent and the usage will start on the same line; else
  705. // the usage will start on the next line with an indent. Also,
  706. // the null-terminator is NOT accounted for in this value.
  707. //
  708. cchSwitch = (USHORT) (usSwitchIndent + _ncslen(nszSeparator)
  709. + _ncslen(_pnszSwitch) ) ;
  710. if (cchSwitch < usUsageIndent)
  711. {
  712. cchPaddedSwitch = usUsageIndent;
  713. }
  714. else
  715. {
  716. cchPaddedSwitch = (USHORT) (cchSwitch + usUsageIndent
  717. + _ncslen(nszClNewLine) );
  718. }
  719. // Calculate size of usage buffer - null-terminator NOT accounted for
  720. //
  721. cchUsage = (USHORT) (_ncslen(nszType) +
  722. _ncslen(nszSpecify) +
  723. _ncslen(_pnszUsageString) );
  724. // Allocate buffers - add 1 for NULL-terminators
  725. pnszSwitch = new NCHAR[cchPaddedSwitch+1];
  726. pnszUsage = new NCHAR[cchUsage+1];
  727. if (pnszSwitch == NULL || pnszUsage == NULL)
  728. {
  729. delete pnszSwitch;
  730. delete pnszUsage;
  731. return(CMDLINE_ERROR_OUT_OF_MEMORY);
  732. }
  733. // Initialize switch buffer - fill with usSwitchIndent spaces, then
  734. // append the separator and switch, then pad with spaces out to
  735. // usUsageIndent if necessary
  736. //
  737. for (USHORT i=0; i<usSwitchIndent; i++)
  738. {
  739. pnszSwitch[i] = nchClSpace;
  740. }
  741. pnszSwitch[usSwitchIndent] = nchClNull;
  742. _ncscat(pnszSwitch, nszSeparator);
  743. _ncscat(pnszSwitch, _pnszSwitch);
  744. if ((USHORT)_ncslen(pnszSwitch) >= usUsageIndent)
  745. {
  746. // Pad a new line.
  747. _ncscat(pnszSwitch, nszClNewLine);
  748. }
  749. // Pad spaces until usUsageIndemt
  750. for (i = (USHORT) _ncslen(pnszSwitch); i < cchPaddedSwitch; i++)
  751. {
  752. pnszSwitch[i] = nchClSpace;
  753. }
  754. pnszSwitch[cchPaddedSwitch] = nchClNull;
  755. // Initialize usage buffer
  756. _ncscpy(pnszUsage, nszType);
  757. _ncscat(pnszUsage, nszSpecify);
  758. _ncscat(pnszUsage, _pnszUsageString);
  759. // Now we're ready to output the strings - output the switch, then
  760. // set up the values needed to output the usage line.
  761. //
  762. (*_pfnDisplay)(pnszSwitch);
  763. usLineSpaceLeft = (USHORT) (usDisplayWidth - usUsageIndent);
  764. // Output the usage
  765. iRC = DisplayStringByWords(
  766. pnszUsage,
  767. usDisplayWidth,
  768. usUsageIndent,
  769. &usLineSpaceLeft);
  770. if (iRC != CMDLINE_NO_ERROR)
  771. {
  772. delete pnszSwitch;
  773. delete pnszUsage;
  774. return(iRC);
  775. }
  776. // output the special usage
  777. //
  778. iRC = DisplaySpecialUsage(usDisplayWidth, usUsageIndent, &usLineSpaceLeft);
  779. if (iRC != CMDLINE_NO_ERROR)
  780. {
  781. delete pnszSwitch;
  782. delete pnszUsage;
  783. return(iRC);
  784. }
  785. // output the default value string
  786. //
  787. if (_fDefaultSpecified)
  788. {
  789. // Default string is " " + nszDefault + _pnszDefaultValue + "."
  790. pnszDefault = new NCHAR[_ncslen(_pnszDefaultValue) +
  791. _ncslen(nszDefault) + 4];
  792. if (pnszDefault == NULL)
  793. {
  794. iRC = CMDLINE_ERROR_OUT_OF_MEMORY;
  795. }
  796. else
  797. {
  798. _ncscpy(pnszDefault, _TEXTN(" "));
  799. _ncscat(pnszDefault, nszDefault);
  800. _ncscat(pnszDefault, _pnszDefaultValue);
  801. _ncscat(pnszDefault, _TEXTN("."));
  802. iRC = DisplayStringByWords(
  803. pnszDefault,
  804. usDisplayWidth,
  805. usUsageIndent,
  806. &usLineSpaceLeft);
  807. }
  808. if (iRC != CMDLINE_NO_ERROR)
  809. {
  810. delete pnszDefault;
  811. delete pnszSwitch;
  812. delete pnszUsage;
  813. return(iRC);
  814. }
  815. }
  816. // Next thing output should go on a new line
  817. //
  818. (*_pfnDisplay)(nszClNewLine);
  819. delete pnszSwitch;
  820. delete pnszUsage;
  821. delete pnszDefault;
  822. return(iRC);
  823. }
  824. //+-------------------------------------------------------------------
  825. //
  826. // Method: CBaseCmdLineObj::DisplayStringByWords, protected
  827. //
  828. // Synopsis: Writes out the strings word by word following indentation
  829. // and display width rules; words are delimeted by spaces.
  830. // The string begins on the current line at the current
  831. // location (usDisplayWidth-*pusSpaceLeft), including
  832. // any leading space characters.
  833. //
  834. // Arguments: [nszString] - String to output.
  835. // [usDisplayWidth] - Max width allowed to display usage
  836. // [usIndent] - Amount to indent for next line of usage
  837. // [pusSpaceLeft] - Space left on this line
  838. //
  839. // History: 28-Jul-92 davey Created.
  840. //
  841. //--------------------------------------------------------------------
  842. INT CBaseCmdlineObj::DisplayStringByWords(
  843. LPCNSTR nszString,
  844. USHORT usDisplayWidth,
  845. USHORT usIndent,
  846. USHORT *pusSpaceLeft)
  847. {
  848. INT iRC = CMDLINE_NO_ERROR;
  849. BOOL fDone = FALSE;
  850. LPNSTR pnszWord = NULL;
  851. LPCNSTR pnchWord = nszString;
  852. LPCNSTR pnchTrav = nszString;
  853. USHORT i;
  854. // Skip leading spaces, but they are part of the first word
  855. while (nchClSpace == *pnchTrav)
  856. {
  857. pnchTrav++;
  858. }
  859. // Traverse the string until we get to the end
  860. while (!fDone)
  861. {
  862. // Traverse until we find a space, newline, or null
  863. switch(*pnchTrav)
  864. {
  865. case L' ':
  866. // Retrieve the word from the string
  867. iRC = CopyWord(pnchWord, pnchTrav-pnchWord, &pnszWord);
  868. if (iRC == CMDLINE_NO_ERROR)
  869. {
  870. // Output the word
  871. iRC = DisplayWord(
  872. pnszWord,
  873. usDisplayWidth,
  874. usIndent,
  875. pusSpaceLeft);
  876. }
  877. delete pnszWord;
  878. //Set up the next word
  879. pnchWord = pnchTrav++;
  880. // traverse to next non-space character
  881. while (nchClSpace == *pnchTrav)
  882. {
  883. pnchTrav++;
  884. }
  885. break;
  886. case L'\n':
  887. // Retrieve the word from the string, including the newline
  888. iRC = CopyWord(pnchWord, ++pnchTrav-pnchWord, &pnszWord);
  889. if (iRC == CMDLINE_NO_ERROR)
  890. {
  891. // Output the word
  892. iRC = DisplayWord(
  893. pnszWord,
  894. usDisplayWidth,
  895. usIndent,
  896. pusSpaceLeft);
  897. }
  898. delete pnszWord;
  899. // Output usIndent spaces
  900. for (i=0; i<usIndent; i++)
  901. {
  902. (*_pfnDisplay)(nszClSpace);
  903. }
  904. *pusSpaceLeft = (USHORT) (usDisplayWidth - usIndent);
  905. // traverse to next non-space character
  906. while (nchClSpace == *pnchTrav)
  907. {
  908. pnchTrav++;
  909. }
  910. // Set up the next word - note leading blanks are skipped
  911. // so the word will be aligned with the indent
  912. //
  913. pnchWord = pnchTrav;
  914. break;
  915. case L'\0':
  916. // Output the current word
  917. iRC = DisplayWord(
  918. pnchWord,
  919. usDisplayWidth,
  920. usIndent,
  921. pusSpaceLeft);
  922. fDone = TRUE;
  923. break;
  924. default:
  925. // Skip to next character
  926. pnchTrav++;
  927. break;
  928. }
  929. if (iRC != CMDLINE_NO_ERROR)
  930. {
  931. fDone = TRUE;
  932. }
  933. }
  934. return(iRC);
  935. }
  936. //+-------------------------------------------------------------------
  937. //
  938. // Method: CBaseCmdLineObj::CopyWord, protected
  939. //
  940. // Synopsis: Copies cchWord characters starting at pnchWord into a
  941. // null-terminated string buffer (which the caller must
  942. // delete).
  943. //
  944. // Arguments: [pnchWord] - place to copy from.
  945. // [cchWord] - number of characters to copy.
  946. // [ppnszWord] - buffer returned to caller.
  947. //
  948. // History: 15-Oct-93 DeanE Created.
  949. //
  950. //--------------------------------------------------------------------
  951. INT CBaseCmdlineObj::CopyWord(
  952. LPCNSTR pnchWord,
  953. ULONG cchWord,
  954. LPNSTR *ppnszWord)
  955. {
  956. INT iRC = CMDLINE_NO_ERROR;
  957. *ppnszWord = new NCHAR[cchWord+1];
  958. if (NULL == *ppnszWord)
  959. {
  960. iRC = CMDLINE_ERROR_OUT_OF_MEMORY;
  961. }
  962. else
  963. {
  964. _ncsncpy(*ppnszWord, pnchWord, cchWord);
  965. *(*ppnszWord + cchWord) = nchClNull;
  966. }
  967. return(iRC);
  968. }
  969. //+-------------------------------------------------------------------
  970. //
  971. // Method: CBaseCmdLineObj::DisplayWord, protected
  972. //
  973. // Synopsis: Writes out the given word according to the display
  974. // parameters.
  975. //
  976. // Arguments: [nszWord] - word to output.
  977. // [usDisplayWidth] - Max width allowed to display usage.
  978. // [usIndent] - Amount to indent for next line of usage.
  979. // [pusWidth] - Space left on this line.
  980. //
  981. // History: 28-Jul-92 davey Created.
  982. //
  983. //--------------------------------------------------------------------
  984. INT CBaseCmdlineObj::DisplayWord(
  985. LPCNSTR nszWord,
  986. USHORT usDisplayWidth,
  987. USHORT usIndent,
  988. USHORT *pusWidth)
  989. {
  990. INT nRet = CMDLINE_NO_ERROR;
  991. LPCNSTR nszTmp = nszWord;
  992. LPNSTR pnszBuf;
  993. USHORT cchWord;
  994. USHORT cchBuf;
  995. USHORT cchLine = (USHORT) (usDisplayWidth - usIndent);
  996. BOOL fDone = FALSE;
  997. // Add one for leading space
  998. cchWord = (USHORT) _ncslen(nszWord);
  999. // if there is enough room left on the current line, output word
  1000. //
  1001. if (cchWord <= *pusWidth)
  1002. {
  1003. (*_pfnDisplay)(nszWord);
  1004. // update the remaining width
  1005. *pusWidth = (USHORT) (*pusWidth - cchWord);
  1006. }
  1007. else
  1008. {
  1009. // Spit the word out on the next line, traversing more than
  1010. // one line if necessary
  1011. do
  1012. {
  1013. // Calculate how much of the word can be output
  1014. if (_ncslen(nszTmp) <= cchLine)
  1015. {
  1016. cchBuf = (USHORT) _ncslen(nszTmp);
  1017. fDone = TRUE;
  1018. }
  1019. else
  1020. {
  1021. cchBuf = cchLine;
  1022. }
  1023. pnszBuf = new NCHAR[cchBuf+1];
  1024. if (NULL == pnszBuf)
  1025. {
  1026. fDone = TRUE;
  1027. nRet = CMDLINE_ERROR_OUT_OF_MEMORY;
  1028. }
  1029. else
  1030. {
  1031. _ncsncpy(pnszBuf, nszTmp, cchBuf);
  1032. *(pnszBuf+cchBuf) = L'\0';
  1033. }
  1034. nszTmp += cchBuf;
  1035. // Output newline
  1036. (*_pfnDisplay)(nszClNewLine);
  1037. // Indent usIndent spaces
  1038. for (USHORT i=0; i<usIndent; i++)
  1039. {
  1040. (*_pfnDisplay)(nszClSpace);
  1041. }
  1042. // Output buffer
  1043. (*_pfnDisplay)(pnszBuf);
  1044. delete pnszBuf;
  1045. } while (!fDone);
  1046. // Calculate remaining width on the current line
  1047. *pusWidth = (USHORT) (usDisplayWidth - usIndent - cchBuf);
  1048. }
  1049. return(nRet);
  1050. }