Source code of Windows XP (NT5)
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.

325 lines
9.4 KiB

  1. //+------------------------------------------------------------------
  2. //
  3. // File: culong.cxx
  4. //
  5. // Contents: implementation for CUlongCmdlineObj
  6. //
  7. // Synoposis: Encapsulates a command line switch which takes an
  8. // unsigned long value, eg: /maxusers:10
  9. //
  10. // Classes: CUlongCmdlineObj
  11. //
  12. // Functions:
  13. //
  14. // History: 06/15/92 DeanE Stolen from CIntCmdlineObj code
  15. // 07/29/92 davey Added nlsType and nlsLineArgType
  16. // 09/09/92 Lizch Changed SUCCESS to NO_ERROR
  17. // 09/18/92 Lizch Precompile headers
  18. // 11/14/92 DwightKr Updates for new version of NLS_STR
  19. // 10/14/93 DeanE Converted to NCHAR
  20. //
  21. //-------------------------------------------------------------------
  22. #include <comtpch.hxx>
  23. #pragma hdrstop
  24. #include <cmdlinew.hxx> // public cmdlinew stuff
  25. #include "_clw.hxx" // private cmdlinew stuff
  26. #include <ctype.h> // is functions
  27. INT StringToUlong(LPCNSTR pnszInt, ULONG *pUlong);
  28. LPCNSTR nszCmdlineUlong = _TEXTN("Takes an unsigned long ");
  29. LPCNSTR nszLineArgUlong = _TEXTN("<ulong> ");
  30. //+------------------------------------------------------------------
  31. //
  32. // Member: CUlongCmdlineObj destructor
  33. //
  34. // Synoposis: Frees any memory associated with the object
  35. //
  36. // History: Added to allow casting of pValue 05/12/92 Lizch
  37. // Integrated into CUlongCmdlineObj 6/15/92 DeanE
  38. //
  39. //-------------------------------------------------------------------
  40. CUlongCmdlineObj::~CUlongCmdlineObj()
  41. {
  42. delete (ULONG *)_pValue;
  43. _pValue = NULL;
  44. }
  45. //+------------------------------------------------------------------
  46. //
  47. // Member: CUlongCmdlineObj::SetValue, public
  48. //
  49. // Synposis: Stores the ulong value specified after the switch
  50. // string, eg. 10 for /maxusers:10
  51. //
  52. // Effects: This implementation for the virtual method SetValue
  53. // converts the characters following the switch to an unsigned
  54. // long. It allocates memory for the ulong.
  55. // If there is no equator character, or if there
  56. // is no character following the equator character, _pValue
  57. // remains NULL.
  58. //
  59. // Arguments: [nszArg] - the string following the switch on the
  60. // command line. Includes the equator (eg.
  61. // ':' or '=' ), if any.
  62. //
  63. // Returns: CMDLINE_NO_ERROR, CMDLINE_ERROR_OUT_OF_MEMORY,
  64. // CMDLINE_ERROR_TOO_BIG, CMDLINE_ERROR_INVALID_VALUE
  65. //
  66. // History: Created 12/27/91 Lizch
  67. // Converted to NLS_STR 4/17/92 Lizch
  68. // Integrated into CUlongCmdlineObj 6/15/92 DeanE
  69. //
  70. //-------------------------------------------------------------------
  71. INT CUlongCmdlineObj::SetValue(LPCNSTR nszArg)
  72. {
  73. INT iRC;
  74. // delete any existing _pValue
  75. delete (ULONG *)_pValue;
  76. _pValue = NULL;
  77. _pValue = new ULONG;
  78. if (_pValue == NULL)
  79. {
  80. return (CMDLINE_ERROR_OUT_OF_MEMORY);
  81. }
  82. // I'm using this rather than c runtime atol so that I
  83. // can detect error conditions like overflow and non-digits.
  84. iRC = StringToUlong(nszArg, (ULONG *)_pValue);
  85. if (iRC != CMDLINE_NO_ERROR)
  86. {
  87. delete (ULONG *)_pValue;
  88. _pValue = NULL;
  89. }
  90. return(iRC);
  91. }
  92. //+------------------------------------------------------------------
  93. //
  94. // Member: CUlongCmdlineObj::GetValue, public
  95. //
  96. // Synposis: Returns a pointer to ULONG that holds the value.
  97. //
  98. // Arguments: void
  99. //
  100. // Returns: ULONG value at *_pValue.
  101. //
  102. // History: Created 12/27/91 Lizch
  103. // Converted to NLS_STR 4/17/92 Lizch
  104. // Integrated into CUlongCmdlineObj 6/15/92 DeanE
  105. //
  106. //-------------------------------------------------------------------
  107. const ULONG *CUlongCmdlineObj::GetValue()
  108. {
  109. return((ULONG *)_pValue);
  110. }
  111. //+------------------------------------------------------------------
  112. //
  113. // Member: CUlongCmdlineObj::DisplayValue, public
  114. //
  115. // Synoposis: Prints the stored command line value accordint to
  116. // current display method. Generally this will be to stdout.
  117. //
  118. // History: Created 12/27/91 Lizch
  119. // Converted to NLS_STR 4/17/92 Lizch
  120. // Integrated into CUlongCmdlineObj 6/15/92 DeanE
  121. //
  122. //-------------------------------------------------------------------
  123. void CUlongCmdlineObj::DisplayValue()
  124. {
  125. if (_pValue != NULL)
  126. {
  127. _sNprintf(_nszErrorBuf,
  128. _TEXTN("Command line switch %s has value %lu\n"),
  129. _pnszSwitch,
  130. *(ULONG *)_pValue);
  131. (*_pfnDisplay)(_nszErrorBuf);
  132. }
  133. else
  134. {
  135. DisplayNoValue();
  136. }
  137. }
  138. //+------------------------------------------------------------------
  139. //
  140. // Function: StringToUlong
  141. //
  142. // Synoposis: Converts given string to unsigned long, checking for
  143. // overflow and illegal characters. Only +, - and digits
  144. // are accepted.
  145. //
  146. // Arguments: [nszUlong] - string to convert
  147. // [pUlong] - pointer to converted unsigned long
  148. //
  149. // Returns: CMDLINE_NO_ERROR, CMDLINE_ERROR_INVALID_VALUE,
  150. // CMDLINE_ERROR_TOO_BIG
  151. //
  152. // History: Created 12/17/91 Lizch
  153. // Converted to AsciiToUlong 6/15/92 DeanE
  154. // Added in conversion of Hex 12/27/94 DaveY
  155. //
  156. // Notes: I'm using this rather than c runtime atoi so that I
  157. // can detect error conditions like overflow and non-digits.
  158. // The sign is checked for and stored, although it is not
  159. // used - so a negative value will still be converted to
  160. // an unsigned equivalent.
  161. //
  162. //-------------------------------------------------------------------
  163. INT StringToUlong(LPCNSTR nszUlong, ULONG *pUlong)
  164. {
  165. short sNegator = 1;
  166. ULONG ulResult = 0;
  167. INT iRC = CMDLINE_NO_ERROR;
  168. // Skip any leading spaces - these can occur if the command line
  169. // switch incorporates spaces, eg "/a: 123"
  170. //
  171. while (_isnspace(*nszUlong))
  172. {
  173. nszUlong++;
  174. }
  175. // Get sign - ignore for now
  176. switch (*nszUlong)
  177. {
  178. case '-':
  179. sNegator = -1;
  180. nszUlong++;
  181. break;
  182. case '+':
  183. sNegator = 1;
  184. nszUlong++;
  185. break;
  186. default:
  187. break;
  188. }
  189. // see if using hex values
  190. if ((*nszUlong == _TEXTN('0')) &&
  191. ((*(nszUlong+1) == _TEXTN('x')) || (*(nszUlong+1) == _TEXTN('X'))))
  192. {
  193. nszUlong += 2; // pass the "0x"
  194. int max = sizeof(ULONG) << 1; // number of hex digits possible
  195. for(int i=0; *nszUlong != NULL && i < max; i++, nszUlong++)
  196. {
  197. if ((_TEXTN('0') <= *nszUlong ) && (*nszUlong <= _TEXTN('9')))
  198. {
  199. ulResult = ulResult * 16 + (*nszUlong - _TEXTN('0'));
  200. }
  201. else if ((_TEXTN('A') <= *nszUlong ) && (*nszUlong <= _TEXTN('F')))
  202. {
  203. ulResult = ulResult * 16 + 10 + (*nszUlong - _TEXTN('A'));
  204. }
  205. else if ((_TEXTN('a') <= *nszUlong) && (*nszUlong <= _TEXTN('f')))
  206. {
  207. ulResult = ulResult * 16 + 10 + (*nszUlong - _TEXTN('a'));
  208. }
  209. else
  210. {
  211. iRC = CMDLINE_ERROR_INVALID_VALUE;
  212. ulResult = 0;
  213. break;
  214. }
  215. }
  216. if ((i >= max) && (*nszUlong != NULL))
  217. {
  218. iRC = CMDLINE_ERROR_INVALID_VALUE;
  219. ulResult = 0;
  220. }
  221. *pUlong = ulResult;
  222. return iRC;
  223. }
  224. // must be decimal
  225. for (;*nszUlong != L'\0'; nszUlong++)
  226. {
  227. if (!_isndigit(*nszUlong))
  228. {
  229. ulResult = 0;
  230. iRC = CMDLINE_ERROR_INVALID_VALUE;
  231. break;
  232. }
  233. ULONG ulPrevious = ulResult;
  234. ulResult = (ulResult * 10) + (*nszUlong - '0');
  235. // Check for overflow by checking that the previous result is less
  236. // than the current result - if the previous one was bigger, we've
  237. // overflowed!
  238. //
  239. if (ulResult < ulPrevious)
  240. {
  241. ulResult = 0;
  242. iRC = CMDLINE_ERROR_TOO_BIG;
  243. break;
  244. }
  245. }
  246. *pUlong = ulResult;
  247. return(iRC);
  248. }
  249. //+-------------------------------------------------------------------
  250. //
  251. // Method: CUlongCmdlineObj::QueryCmdlineType, protected, const
  252. //
  253. // Synoposis: returns a character pointer to the cmdline type.
  254. //
  255. // Arguments: None.
  256. //
  257. // Returns: const NCHAR pointer to string.
  258. //
  259. // History: 28-Jul-92 davey Created.
  260. //
  261. //--------------------------------------------------------------------
  262. LPCNSTR CUlongCmdlineObj::QueryCmdlineType() const
  263. {
  264. return(nszCmdlineUlong);
  265. }
  266. //+-------------------------------------------------------------------
  267. //
  268. // Method: CUlongCmdlineObj::QueryLineArgType, protected, const
  269. //
  270. // Synoposis: returns a character pointer to the line arg type.
  271. //
  272. // Arguments: None.
  273. //
  274. // Returns: const NLS_STR reference to string.
  275. //
  276. // History: 28-Jul-92 davey Created.
  277. //
  278. //--------------------------------------------------------------------
  279. LPCNSTR CUlongCmdlineObj::QueryLineArgType() const
  280. {
  281. // if user has not defined one then give default one
  282. if (_pnszLineArgType == NULL)
  283. {
  284. return(nszLineArgUlong);
  285. }
  286. else
  287. {
  288. return(_pnszLineArgType);
  289. }
  290. }