選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

4031 行
196 KiB

  1. /*
  2. *********************************************************************************************************
  3. * uC/LIB
  4. * Custom Library Modules
  5. *
  6. * Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com
  7. *
  8. * SPDX-License-Identifier: APACHE-2.0
  9. *
  10. * This software is subject to an open source license and is distributed by
  11. * Silicon Laboratories Inc. pursuant to the terms of the Apache License,
  12. * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
  13. *
  14. *********************************************************************************************************
  15. */
  16. /*
  17. *********************************************************************************************************
  18. *
  19. * ASCII STRING MANAGEMENT
  20. *
  21. * Filename : lib_str.c
  22. * Version : V1.39.01
  23. *********************************************************************************************************
  24. * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software.
  25. *
  26. * (a) ALL standard library functions are implemented in the custom library modules :
  27. *
  28. * (1) \<Custom Library Directory>\lib_*.*
  29. *
  30. * (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
  31. *
  32. * where
  33. * <Custom Library Directory> directory path for custom library software
  34. * <cpu> directory name for specific processor (CPU)
  35. * <compiler> directory name for specific compiler
  36. *
  37. * (b) Product-specific library functions are implemented in individual products.
  38. *
  39. *********************************************************************************************************
  40. * Notice(s) : (1) The Institute of Electrical and Electronics Engineers and The Open Group, have given
  41. * us permission to reprint portions of their documentation. Portions of this text are
  42. * reprinted and reproduced in electronic form from the IEEE Std 1003.1, 2004 Edition,
  43. * Standard for Information Technology -- Portable Operating System Interface (POSIX),
  44. * The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute
  45. * of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any
  46. * discrepancy between these versions and the original IEEE and The Open Group Standard,
  47. * the original IEEE and The Open Group Standard is the referee document. The original
  48. * Standard can be obtained online at http://www.opengroup.org/unix/online.html.
  49. *********************************************************************************************************
  50. */
  51. /*
  52. *********************************************************************************************************
  53. * INCLUDE FILES
  54. *********************************************************************************************************
  55. */
  56. #define MICRIUM_SOURCE
  57. #define LIB_STR_MODULE
  58. #include <lib_str.h>
  59. /*
  60. *********************************************************************************************************
  61. * LOCAL DEFINES
  62. *********************************************************************************************************
  63. */
  64. /*
  65. *********************************************************************************************************
  66. * LOCAL CONSTANTS
  67. *********************************************************************************************************
  68. */
  69. /*
  70. *********************************************************************************************************
  71. * LOCAL DATA TYPES
  72. *********************************************************************************************************
  73. */
  74. /*
  75. *********************************************************************************************************
  76. * LOCAL TABLES
  77. *********************************************************************************************************
  78. */
  79. static const CPU_INT32U Str_MultOvfThTbl_Int32U[] = {
  80. (CPU_INT32U) DEF_INT_32U_MAX_VAL, /* Invalid base 0. */
  81. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 1u), /* Invalid base 1. */
  82. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 2u), /* 32-bit mult ovf th for base 2. */
  83. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 3u), /* 32-bit mult ovf th for base 3. */
  84. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 4u), /* 32-bit mult ovf th for base 4. */
  85. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 5u), /* 32-bit mult ovf th for base 5. */
  86. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 6u), /* 32-bit mult ovf th for base 6. */
  87. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 7u), /* 32-bit mult ovf th for base 7. */
  88. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 8u), /* 32-bit mult ovf th for base 8. */
  89. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 9u), /* 32-bit mult ovf th for base 9. */
  90. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 10u), /* 32-bit mult ovf th for base 10. */
  91. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 11u), /* 32-bit mult ovf th for base 11. */
  92. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 12u), /* 32-bit mult ovf th for base 12. */
  93. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 13u), /* 32-bit mult ovf th for base 13. */
  94. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 14u), /* 32-bit mult ovf th for base 14. */
  95. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 15u), /* 32-bit mult ovf th for base 15. */
  96. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 16u), /* 32-bit mult ovf th for base 16. */
  97. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 17u), /* 32-bit mult ovf th for base 17. */
  98. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 18u), /* 32-bit mult ovf th for base 18. */
  99. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 19u), /* 32-bit mult ovf th for base 19. */
  100. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 20u), /* 32-bit mult ovf th for base 20. */
  101. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 21u), /* 32-bit mult ovf th for base 21. */
  102. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 22u), /* 32-bit mult ovf th for base 22. */
  103. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 23u), /* 32-bit mult ovf th for base 23. */
  104. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 24u), /* 32-bit mult ovf th for base 24. */
  105. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 25u), /* 32-bit mult ovf th for base 25. */
  106. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 26u), /* 32-bit mult ovf th for base 26. */
  107. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 27u), /* 32-bit mult ovf th for base 27. */
  108. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 28u), /* 32-bit mult ovf th for base 28. */
  109. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 29u), /* 32-bit mult ovf th for base 29. */
  110. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 30u), /* 32-bit mult ovf th for base 30. */
  111. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 31u), /* 32-bit mult ovf th for base 31. */
  112. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 32u), /* 32-bit mult ovf th for base 32. */
  113. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 33u), /* 32-bit mult ovf th for base 33. */
  114. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 34u), /* 32-bit mult ovf th for base 34. */
  115. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 35u), /* 32-bit mult ovf th for base 35. */
  116. (CPU_INT32U)(DEF_INT_32U_MAX_VAL / 36u) /* 32-bit mult ovf th for base 36. */
  117. };
  118. /*
  119. *********************************************************************************************************
  120. * LOCAL GLOBAL VARIABLES
  121. *********************************************************************************************************
  122. */
  123. /*
  124. *********************************************************************************************************
  125. * LOCAL FUNCTION PROTOTYPES
  126. *********************************************************************************************************
  127. */
  128. static CPU_CHAR *Str_FmtNbr_Int32 ( CPU_INT32U nbr,
  129. CPU_INT08U nbr_dig,
  130. CPU_INT08U nbr_base,
  131. CPU_BOOLEAN nbr_neg,
  132. CPU_CHAR lead_char,
  133. CPU_BOOLEAN lower_case,
  134. CPU_BOOLEAN nul,
  135. CPU_CHAR *pstr);
  136. static CPU_INT32U Str_ParseNbr_Int32(const CPU_CHAR *pstr,
  137. CPU_CHAR **pstr_next,
  138. CPU_INT08U nbr_base,
  139. CPU_BOOLEAN nbr_signed,
  140. CPU_BOOLEAN *pnbr_neg);
  141. /*
  142. *********************************************************************************************************
  143. * LOCAL CONFIGURATION ERRORS
  144. *********************************************************************************************************
  145. */
  146. /*
  147. *********************************************************************************************************
  148. * Str_Len()
  149. *
  150. * Description : Calculate length of a string.
  151. *
  152. * Argument(s) : pstr Pointer to string (see Note #1).
  153. *
  154. * Return(s) : Length of string; number of characters in string before terminating NULL character
  155. * (see Note #2b1).
  156. *
  157. * Caller(s) : Application.
  158. *
  159. * Note(s) : (1) String buffer NOT modified.
  160. *
  161. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : DESCRIPTION' states that :
  162. *
  163. * (1) "The strlen() function shall compute the number of bytes in the string to
  164. * which 's' ('pstr') points," ...
  165. * (2) "not including the terminating null byte."
  166. *
  167. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : RETURN VALUE' states that :
  168. *
  169. * (1) "The strlen() function shall return the length of 's' ('pstr');" ...
  170. * (2) "no return value shall be reserved to indicate an error."
  171. *
  172. * (3) String length calculation terminates when :
  173. *
  174. * (a) String pointer points to NULL.
  175. * (1) String buffer overlaps with NULL address.
  176. * (2) String length calculated for string up to but NOT beyond or including
  177. * the NULL address.
  178. *
  179. * (b) Terminating NULL character found.
  180. * (1) String length calculated for string up to but NOT including
  181. * the NULL character (see Note #2a2).
  182. *********************************************************************************************************
  183. */
  184. CPU_SIZE_T Str_Len (const CPU_CHAR *pstr)
  185. {
  186. CPU_SIZE_T len;
  187. len = Str_Len_N(pstr,
  188. DEF_INT_CPU_U_MAX_VAL);
  189. return (len);
  190. }
  191. /*
  192. *********************************************************************************************************
  193. * Str_Len_N()
  194. *
  195. * Description : Calculate length of a string, up to a maximum number of characters.
  196. *
  197. * Argument(s) : pstr Pointer to string (see Note #1).
  198. *
  199. * len_max Maximum number of characters to search (see Note #3c).
  200. *
  201. * Return(s) : Length of string; number of characters in string before terminating NULL character,
  202. * if terminating NULL character found (see Note #2b1).
  203. *
  204. * Requested maximum number of characters to search,
  205. * if terminating NULL character NOT found (see Note #3c).
  206. *
  207. * Caller(s) : Application.
  208. *
  209. * Note(s) : (1) String buffer NOT modified.
  210. *
  211. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : DESCRIPTION' states that :
  212. *
  213. * (1) "The strlen() function shall compute the number of bytes in the string to
  214. * which 's' ('pstr') points," ...
  215. * (2) "not including the terminating null byte."
  216. *
  217. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strlen() : RETURN VALUE' states that :
  218. *
  219. * (1) "The strlen() function shall return the length of 's' ('pstr');" ...
  220. * (2) "no return value shall be reserved to indicate an error."
  221. *
  222. * (3) String length calculation terminates when :
  223. *
  224. * (a) String pointer points to NULL.
  225. * (1) String buffer overlaps with NULL address.
  226. * (2) String length calculated for string up to but NOT beyond or including
  227. * the NULL address.
  228. *
  229. * (b) Terminating NULL character found.
  230. * (1) String length calculated for string up to but NOT including
  231. * the NULL character (see Note #2a2).
  232. *
  233. * (c) 'len_max' number of characters searched.
  234. * (1) 'len_max' number of characters does NOT include the terminating NULL character.
  235. *********************************************************************************************************
  236. */
  237. CPU_SIZE_T Str_Len_N (const CPU_CHAR *pstr,
  238. CPU_SIZE_T len_max)
  239. {
  240. const CPU_CHAR *pstr_len;
  241. CPU_SIZE_T len;
  242. pstr_len = pstr;
  243. len = 0u;
  244. while (( pstr_len != (const CPU_CHAR *) 0 ) && /* Calc str len until NULL ptr (see Note #3a) ... */
  245. (*pstr_len != ( CPU_CHAR )'\0') && /* ... or NULL char found (see Note #3b) ... */
  246. ( len < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars srch'd (see Note #3c). */
  247. pstr_len++;
  248. len++;
  249. }
  250. return (len); /* Rtn str len (see Note #3b1). */
  251. }
  252. /*
  253. *********************************************************************************************************
  254. * Str_Copy()
  255. *
  256. * Description : Copy source string to destination string buffer.
  257. *
  258. * Argument(s) : pstr_dest Pointer to destination string buffer to receive source string copy (see Note #1a).
  259. *
  260. * pstr_src Pointer to source string to copy into destination string buffer (see Note #1b).
  261. *
  262. * Return(s) : Pointer to destination string, if NO error(s) [see Note #2b1].
  263. *
  264. * Pointer to NULL, otherwise (see Note #2b2A).
  265. *
  266. * Caller(s) : Application.
  267. *
  268. * Note(s) : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
  269. *
  270. * (1) Destination buffer size MUST be large enough to accommodate the entire source
  271. * string size including the terminating NULL character.
  272. *
  273. * (b) Source buffer NOT modified.
  274. *
  275. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcpy() : DESCRIPTION' states that :
  276. *
  277. * (1) "The strcpy() function shall copy the string pointed to by 's2' ('pstr_src')
  278. * ... into the array pointed to by 's1' ('pstr_dest')" ...
  279. * (2) "(including the terminating null byte)."
  280. *
  281. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strcpy() : RETURN VALUE' states that :
  282. *
  283. * (1) "The strcpy() function shall return 's1' ('pstr_dest');" ...
  284. * (2) "no return value is reserved to indicate an error."
  285. * (A) #### This requirement is intentionally NOT implemented in order to return
  286. * NULL for any error(s).
  287. *
  288. * (c) IEEE Std 1003.1, 2004 Edition, Section 'strcpy() : DESCRIPTION' states that "if
  289. * copying takes place between objects that overlap, the behavior is undefined".
  290. *
  291. * (3) String copy terminates when :
  292. *
  293. * (a) Destination/Source string pointer(s) are passed NULL pointers.
  294. * (1) No string copy performed; NULL pointer returned.
  295. *
  296. * (b) Destination/Source string pointer(s) point to NULL.
  297. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  298. *
  299. * (c) Source string's terminating NULL character found.
  300. * (1) Entire source string copied into destination string buffer (see Note #2a).
  301. *********************************************************************************************************
  302. */
  303. CPU_CHAR *Str_Copy ( CPU_CHAR *pstr_dest,
  304. const CPU_CHAR *pstr_src)
  305. {
  306. CPU_CHAR *pstr_rtn;
  307. pstr_rtn = Str_Copy_N(pstr_dest,
  308. pstr_src,
  309. DEF_INT_CPU_U_MAX_VAL);
  310. return (pstr_rtn);
  311. }
  312. /*
  313. *********************************************************************************************************
  314. * Str_Copy_N()
  315. *
  316. * Description : Copy source string to destination string buffer, up to a maximum number of characters.
  317. *
  318. * Argument(s) : pstr_dest Pointer to destination string buffer to receive source string copy (see Note #1a).
  319. *
  320. * pstr_src Pointer to source string to copy into destination string buffer (see Note #1b).
  321. *
  322. * len_max Maximum number of characters to copy (see Notes #2a2 & #3d).
  323. *
  324. * Return(s) : Pointer to destination string, if NO error(s) [see Note #2b1].
  325. *
  326. * Pointer to NULL, otherwise (see Note #2b2A).
  327. *
  328. * Caller(s) : Application.
  329. *
  330. * Note(s) : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
  331. *
  332. * (1) Destination buffer size MUST be large enough to accommodate the entire source
  333. * string size including the terminating NULL character.
  334. *
  335. * (b) Source string buffer NOT modified.
  336. *
  337. * (2) (a) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : DESCRIPTION' states that :
  338. *
  339. * (A) "The strncpy() function shall copy ... the array pointed to by 's2'
  340. * ('pstr_src') to the array pointed to by 's1' ('pstr_dest')"; ...
  341. * (B) but "not more than 'n' ('len_max') bytes" ...
  342. * (C) & "(bytes that follow a null byte are not copied)".
  343. *
  344. * (2) (A) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : DESCRIPTION' adds that
  345. * "if the array pointed to by 's2' ('pstr_src') is a string that is shorter
  346. * than 'n' ('len_max') bytes, null bytes shall be appended to the copy in
  347. * the array pointed to by 's1' ('pstr_dest'), until 'n' ('len_max') bytes
  348. * in all are written."
  349. *
  350. * (1) #### Since Str_Copy() limits the maximum number of characters to copy
  351. * via Str_Copy_N() by the CPU's maximum number of addressable characters,
  352. * this requirement is intentionally NOT implemented to avoid appending
  353. * a potentially large number of unnecessary terminating NULL characters.
  354. *
  355. * (B) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : APPLICATION USAGE' also
  356. * states that "if there is no null byte in the first 'n' ('len_max') bytes of
  357. * the array pointed to by 's2' ('pstr_src'), the result is not null-terminated".
  358. *
  359. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : RETURN VALUE' states that :
  360. *
  361. * (1) "The strncpy() function shall return 's1' ('pstr_dest');" ...
  362. * (2) "no return value is reserved to indicate an error."
  363. * (A) #### This requirement is intentionally ignored in order to return NULL
  364. * for any error(s).
  365. *
  366. * (c) IEEE Std 1003.1, 2004 Edition, Section 'strncpy() : DESCRIPTION' states that "if
  367. * copying takes place between objects that overlap, the behavior is undefined".
  368. *
  369. * (3) String copy terminates when :
  370. *
  371. * (a) Destination/Source string pointer(s) are passed NULL pointers.
  372. * (1) No string copy performed; NULL pointer returned.
  373. *
  374. * (b) Destination/Source string pointer(s) point to NULL.
  375. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  376. *
  377. * (c) Source string's terminating NULL character found.
  378. * (1) Entire source string copied into destination string buffer (see Note #2a1A).
  379. *
  380. * (d) 'len_max' number of characters copied.
  381. * (1) 'len_max' number of characters MAY include the terminating NULL character
  382. * (see Note #2a1C).
  383. * (2) Null copies allowed (i.e. zero-length copies).
  384. * (A) No string copy performed; destination string returned (see Note #2b1).
  385. *********************************************************************************************************
  386. */
  387. CPU_CHAR *Str_Copy_N ( CPU_CHAR *pstr_dest,
  388. const CPU_CHAR *pstr_src,
  389. CPU_SIZE_T len_max)
  390. {
  391. CPU_CHAR *pstr_copy_dest;
  392. const CPU_CHAR *pstr_copy_src;
  393. CPU_SIZE_T len_copy;
  394. /* Rtn NULL if str ptr(s) NULL (see Note #3a1). */
  395. if (pstr_dest == (CPU_CHAR *)0) {
  396. return ((CPU_CHAR *)0);
  397. }
  398. if (pstr_src == (const CPU_CHAR *)0) {
  399. return ((CPU_CHAR *)0);
  400. }
  401. pstr_copy_dest = pstr_dest;
  402. pstr_copy_src = pstr_src;
  403. len_copy = 0u;
  404. while (( pstr_copy_dest != ( CPU_CHAR *) 0 ) && /* Copy str until NULL ptr(s) [see Note #3b] ... */
  405. ( pstr_copy_src != (const CPU_CHAR *) 0 ) &&
  406. (*pstr_copy_src != ( CPU_CHAR )'\0') && /* ... or NULL char found (see Note #3c); ... */
  407. ( len_copy < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars copied (see Note #3d). */
  408. *pstr_copy_dest = *pstr_copy_src;
  409. pstr_copy_dest++;
  410. pstr_copy_src++;
  411. len_copy++;
  412. }
  413. /* Rtn NULL if NULL ptr(s) found (see Note #3b1). */
  414. if ((pstr_copy_dest == ( CPU_CHAR *)0) ||
  415. (pstr_copy_src == (const CPU_CHAR *)0)) {
  416. return ((CPU_CHAR *)0);
  417. }
  418. if (len_copy < len_max) { /* If copy str len < max buf len (see Note #2a2A), ... */
  419. *pstr_copy_dest = (CPU_CHAR)'\0'; /* ... copy NULL char (see Note #3c1). */
  420. }
  421. return (pstr_dest); /* Rtn ptr to dest str (see Note #2b1). */
  422. }
  423. /*
  424. *********************************************************************************************************
  425. * Str_Cat()
  426. *
  427. * Description : Append concatenation string to destination string.
  428. *
  429. * Argument(s) : pstr_dest Pointer to destination string to append concatenation string (see Note #1a).
  430. *
  431. * pstr_cat Pointer to concatenation string to append to destination string (see Note #1b).
  432. *
  433. * Return(s) : Pointer to destination string, if NO error(s) [see Note #2b1].
  434. *
  435. * Pointer to NULL, otherwise (see Note #2b2A).
  436. *
  437. * Caller(s) : Application.
  438. *
  439. * Note(s) : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
  440. *
  441. * (1) Destination buffer size MUST be large enough to accommodate the entire
  442. * concatenated string size including the terminating NULL character.
  443. *
  444. * (b) Concatenation string buffer NOT modified.
  445. *
  446. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcat() : DESCRIPTION' states that :
  447. *
  448. * (1) "The strcat() function shall append a copy of the string pointed to by 's2'
  449. * ('pstr_cat') ... to the end of the string pointed to by 's1' ('pstr_dest')."
  450. *
  451. * (2) (A) "The initial byte of 's2' ('pstr_cat') overwrites the null byte at the
  452. * end of 's1' ('pstr_dest')."
  453. * (B) A "terminating null byte" is appended at the end of the concatenated
  454. * destination strings.
  455. *
  456. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strcat() : RETURN VALUE' states that :
  457. *
  458. * (1) "The strcat() function shall return 's1' ('pstr_dest');" ...
  459. * (2) "no return value shall be reserved to indicate an error."
  460. * (A) #### This requirement is intentionally NOT implemented in order to return
  461. * NULL for any error(s).
  462. *
  463. * (c) IEEE Std 1003.1, 2004 Edition, Section 'strcat() : DESCRIPTION' states that "if
  464. * copying takes place between objects that overlap, the behavior is undefined."
  465. *
  466. * (3) String concatenation terminates when :
  467. *
  468. * (a) Destination/Concatenation string pointer(s) are passed NULL pointers.
  469. * (1) No string concatenation performed; NULL pointer returned.
  470. *
  471. * (b) Destination/Concatenation string pointer(s) point to NULL.
  472. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  473. *
  474. * (c) Concatenation string's terminating NULL character found.
  475. * (1) Entire concatenation string appended to destination string (see Note #2a1).
  476. *********************************************************************************************************
  477. */
  478. CPU_CHAR *Str_Cat ( CPU_CHAR *pstr_dest,
  479. const CPU_CHAR *pstr_cat)
  480. {
  481. CPU_CHAR *pstr_rtn;
  482. pstr_rtn = Str_Cat_N(pstr_dest,
  483. pstr_cat,
  484. DEF_INT_CPU_U_MAX_VAL);
  485. return (pstr_rtn);
  486. }
  487. /*
  488. *********************************************************************************************************
  489. * Str_Cat_N()
  490. *
  491. * Description : Append concatenation string to destination string, up to a maximum number of characters.
  492. *
  493. * Argument(s) : pstr_dest Pointer to destination string to append concatenation string (see Note #1a).
  494. *
  495. * pstr_cat Pointer to concatenation string to append to destination string (see Note #1b).
  496. *
  497. * len_max Maximum number of characters to concatenate (see Notes #2a1B & #3d).
  498. *
  499. * Return(s) : Pointer to destination string, if NO error(s) [see Note #2b1].
  500. *
  501. * Pointer to NULL, otherwise (see Note #2b2A).
  502. *
  503. * Caller(s) : Application.
  504. *
  505. * Note(s) : (1) (a) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
  506. *
  507. * (1) Destination buffer size MUST be large enough to accommodate the entire
  508. * concatenated string size including the terminating NULL character.
  509. *
  510. * (b) Concatenation string buffer NOT modified.
  511. *
  512. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncat() : DESCRIPTION' states that :
  513. *
  514. * (1) (A) "The strncat() function shall append ... the array pointed to by 's2'
  515. * ('pstr_cat') to the end of the string pointed to by 's1' ('pstr_dest')" ...
  516. * (B) but "not more than 'n' ('len_max') bytes".
  517. *
  518. * (2) (A) "The initial byte of 's2' ('pstr_cat') overwrites the null byte at the
  519. * end of 's1' ('pstr_dest')."
  520. * (B) "(a null byte and bytes that follow it are not appended)."
  521. * (C) "A terminating null byte is always appended to the result."
  522. *
  523. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strncat() : RETURN VALUE' states that :
  524. *
  525. * (1) "The strncat() function shall return 's1' ('pstr_dest');" ...
  526. * (2) "no return value shall be reserved to indicate an error."
  527. * (A) #### This requirement is intentionally NOT implemented in order to return
  528. * NULL for any error(s).
  529. *
  530. * (c) IEEE Std 1003.1, 2004 Edition, Section 'strncat() : DESCRIPTION' states that "if
  531. * copying takes place between objects that overlap, the behavior is undefined."
  532. *
  533. * (3) String concatenation terminates when :
  534. *
  535. * (a) Destination/Concatenation string pointer(s) are passed NULL pointers.
  536. * (1) No string concatenation performed; NULL pointer returned.
  537. *
  538. * (b) Destination/Concatenation string pointer(s) point to NULL.
  539. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  540. *
  541. * (c) Concatenation string's terminating NULL character found.
  542. * (1) Entire concatenation string appended to destination string (see Note #2a1A).
  543. *
  544. * (d) 'len_max' number of characters concatenated.
  545. *
  546. * (1) 'len_max' number of characters does NOT include the terminating NULL character
  547. * (see Note #2a2).
  548. *
  549. * (2) Null concatenations allowed (i.e. zero-length concatenations).
  550. * (A) No string concatenation performed; destination string returned
  551. * (see Note #2b1).
  552. *********************************************************************************************************
  553. */
  554. CPU_CHAR *Str_Cat_N ( CPU_CHAR *pstr_dest,
  555. const CPU_CHAR *pstr_cat,
  556. CPU_SIZE_T len_max)
  557. {
  558. CPU_CHAR *pstr_cat_dest;
  559. const CPU_CHAR *pstr_cat_src;
  560. CPU_SIZE_T len_cat;
  561. /* Rtn NULL if str ptr(s) NULL (see Note #3a1). */
  562. if (pstr_dest == (CPU_CHAR *)0) {
  563. return ((CPU_CHAR *)0);
  564. }
  565. if (pstr_cat == (const CPU_CHAR *)0) {
  566. return ((CPU_CHAR *)0);
  567. }
  568. if (len_max < 1) { /* Rtn dest str if cat len = 0 (see Note #3d2A). */
  569. return ((CPU_CHAR *)pstr_dest);
  570. }
  571. pstr_cat_dest = pstr_dest;
  572. while (( pstr_cat_dest != (CPU_CHAR *) 0 ) && /* Adv to end of cur dest str until NULL ptr ... */
  573. (*pstr_cat_dest != (CPU_CHAR )'\0')) { /* ... or NULL char found.. */
  574. pstr_cat_dest++;
  575. }
  576. if (pstr_cat_dest == (CPU_CHAR *)0) { /* Rtn NULL if NULL ptr found (see Note #3b1). */
  577. return ((CPU_CHAR *)0);
  578. }
  579. pstr_cat_src = pstr_cat;
  580. len_cat = 0u;
  581. while (( pstr_cat_dest != ( CPU_CHAR *) 0 ) && /* Cat str until NULL ptr(s) [see Note #3b] ... */
  582. ( pstr_cat_src != (const CPU_CHAR *) 0 ) &&
  583. (*pstr_cat_src != ( CPU_CHAR )'\0') && /* ... or NULL char found (see Note #3c); ... */
  584. ( len_cat < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars cat'd (see Note #3d). */
  585. *pstr_cat_dest = *pstr_cat_src;
  586. pstr_cat_dest++;
  587. pstr_cat_src++;
  588. len_cat++;
  589. }
  590. /* Rtn NULL if NULL ptr(s) found (see Note #3b1). */
  591. if ((pstr_cat_dest == ( CPU_CHAR *)0) ||
  592. (pstr_cat_src == (const CPU_CHAR *)0)) {
  593. return ((CPU_CHAR *)0);
  594. }
  595. *pstr_cat_dest = (CPU_CHAR)'\0'; /* Append NULL char (see Note #2a2C). */
  596. return (pstr_dest); /* Rtn ptr to dest str (see Note #2b1). */
  597. }
  598. /*
  599. *********************************************************************************************************
  600. * Str_Cmp()
  601. *
  602. * Description : Determine if two strings are identical.
  603. *
  604. * Argument(s) : p1_str Pointer to first string (see Note #1).
  605. *
  606. * p2_str Pointer to second string (see Note #1).
  607. *
  608. * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, & #3b).
  609. *
  610. * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
  611. *
  612. * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
  613. *
  614. * See also Note #2b.
  615. *
  616. * Caller(s) : Application.
  617. *
  618. * Note(s) : (1) String buffers NOT modified.
  619. *
  620. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' states that "the
  621. * strcmp() function shall compare the string pointed to by 's1' ('p1_str') to the
  622. * string pointed to by 's2' ('p2_str)".
  623. *
  624. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : RETURN VALUE' states that
  625. * "upon successful completion, strcmp() shall return an integer greater than,
  626. * equal to, or less than 0".
  627. *
  628. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
  629. * sign of a non-zero return value shall be determined by the sign of the difference
  630. * between the values of the first pair of bytes ... that differ in the strings
  631. * being compared".
  632. *
  633. * (3) String comparison terminates when :
  634. *
  635. * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
  636. * (1) NULL strings identical; 0 returned.
  637. *
  638. * (B) (1) 'p1_str' passed a NULL pointer.
  639. * (a) Return negative value of character pointed to by 'p2_str'.
  640. *
  641. * (2) 'p2_str' passed a NULL pointer.
  642. * (a) Return positive value of character pointed to by 'p1_str'.
  643. *
  644. * (2) (A) BOTH strings point to NULL.
  645. * (1) Strings overlap with NULL address.
  646. * (2) Strings identical up to but NOT beyond or including the NULL address;
  647. * 0 returned.
  648. *
  649. * (B) (1) 'p1_str_cmp_next' points to NULL.
  650. * (a) 'p1_str' overlaps with NULL address.
  651. * (b) Strings compared up to but NOT beyond or including the NULL address.
  652. * (c) Return negative value of character pointed to by 'p2_str_cmp_next'.
  653. *
  654. * (2) 'p2_str_cmp_next' points to NULL.
  655. * (a) 'p2_str' overlaps with NULL address.
  656. * (b) Strings compared up to but NOT beyond or including the NULL address.
  657. * (c) Return positive value of character pointed to by 'p1_str_cmp_next'.
  658. *
  659. * (b) Terminating NULL character found in both strings.
  660. * (1) Strings identical; 0 returned.
  661. * (2) Only one NULL character test required in conditional since previous condition
  662. * tested character equality.
  663. *
  664. * (c) Non-matching characters found.
  665. * (1) Return signed-integer difference of the character pointed to by 'p2_str'
  666. * from the character pointed to by 'p1_str'.
  667. *
  668. * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
  669. * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
  670. *********************************************************************************************************
  671. */
  672. CPU_INT16S Str_Cmp (const CPU_CHAR *p1_str,
  673. const CPU_CHAR *p2_str)
  674. {
  675. CPU_INT16S cmp_val;
  676. cmp_val = Str_Cmp_N(p1_str,
  677. p2_str,
  678. DEF_INT_CPU_U_MAX_VAL);
  679. return (cmp_val);
  680. }
  681. /*
  682. *********************************************************************************************************
  683. * Str_Cmp_N()
  684. *
  685. * Description : Determine if two strings are identical for up to a maximum number of characters.
  686. *
  687. * Argument(s) : p1_str Pointer to first string (see Note #1).
  688. *
  689. * p2_str Pointer to second string (see Note #1).
  690. *
  691. * len_max Maximum number of characters to compare (see Note #3d).
  692. *
  693. * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, #3b, & #3d).
  694. *
  695. * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
  696. *
  697. * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
  698. *
  699. * See also Note #2b.
  700. *
  701. * Caller(s) : Application.
  702. *
  703. * Note(s) : (1) String buffers NOT modified.
  704. *
  705. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : DESCRIPTION' states that :
  706. *
  707. * (1) "The strncmp() function shall compare ... the array pointed to by 's1' ('p1_str')
  708. * to the array pointed to by 's2' ('p2_str)" ...
  709. * (2) but "not more than 'n' ('len_max') bytes" of either array.
  710. *
  711. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : RETURN VALUE' states that
  712. * "upon successful completion, strncmp() shall return an integer greater than,
  713. * equal to, or less than 0".
  714. *
  715. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : DESCRIPTION' adds that
  716. * "the sign of a non-zero return value is determined by the sign of the difference
  717. * between the values of the first pair of bytes ... that differ in the strings
  718. * being compared".
  719. *
  720. * (3) String comparison terminates when :
  721. *
  722. * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
  723. * (1) NULL strings identical; 0 returned.
  724. *
  725. * (B) (1) 'p1_str' passed a NULL pointer.
  726. * (a) Return negative value of character pointed to by 'p2_str'.
  727. *
  728. * (2) 'p2_str' passed a NULL pointer.
  729. * (a) Return positive value of character pointed to by 'p1_str'.
  730. *
  731. * (2) (A) BOTH strings point to NULL.
  732. * (1) Strings overlap with NULL address.
  733. * (2) Strings identical up to but NOT beyond or including the NULL address;
  734. * 0 returned.
  735. *
  736. * (B) (1) 'p1_str_cmp_next' points to NULL.
  737. * (a) 'p1_str' overlaps with NULL address.
  738. * (b) Strings compared up to but NOT beyond or including the NULL address.
  739. * (c) Return negative value of character pointed to by 'p2_str_cmp_next'.
  740. *
  741. * (2) 'p2_str_cmp_next' points to NULL.
  742. * (a) 'p2_str' overlaps with NULL address.
  743. * (b) Strings compared up to but NOT beyond or including the NULL address.
  744. * (c) Return positive value of character pointed to by 'p1_str_cmp_next'.
  745. *
  746. * (b) Terminating NULL character found in both strings.
  747. * (1) Strings identical; 0 returned.
  748. * (2) Only one NULL character test required in conditional since previous condition
  749. * tested character equality.
  750. *
  751. * (c) Non-matching characters found.
  752. * (1) Return signed-integer difference of the character pointed to by 'p2_str'
  753. * from the character pointed to by 'p1_str'.
  754. *
  755. * (d) (1) 'len_max' passed a zero length.
  756. * (A) Zero-length strings identical; 0 returned.
  757. *
  758. * (2) First 'len_max' number of characters identical.
  759. * (A) Strings identical; 0 returned.
  760. *
  761. * See also Note #2a2.
  762. *
  763. * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
  764. * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
  765. *********************************************************************************************************
  766. */
  767. CPU_INT16S Str_Cmp_N (const CPU_CHAR *p1_str,
  768. const CPU_CHAR *p2_str,
  769. CPU_SIZE_T len_max)
  770. {
  771. const CPU_CHAR *p1_str_cmp;
  772. const CPU_CHAR *p2_str_cmp;
  773. const CPU_CHAR *p1_str_cmp_next;
  774. const CPU_CHAR *p2_str_cmp_next;
  775. CPU_INT16S cmp_val;
  776. CPU_SIZE_T cmp_len;
  777. if (len_max < 1) { /* If cmp len = 0, rtn 0 (see Note #3d1A). */
  778. return (0);
  779. }
  780. if (p1_str == (const CPU_CHAR *)0) {
  781. if (p2_str == (const CPU_CHAR *)0) {
  782. return (0); /* If BOTH str ptrs NULL, rtn 0 (see Note #3a1A). */
  783. }
  784. cmp_val = (CPU_INT16S)((CPU_INT16S)0 - (CPU_INT16S)(*p2_str));
  785. return (cmp_val); /* If p1_str NULL, rtn neg p2_str val (see Note #3a1B1).*/
  786. }
  787. if (p2_str == (const CPU_CHAR *)0) {
  788. cmp_val = (CPU_INT16S)(*p1_str);
  789. return (cmp_val); /* If p2_str NULL, rtn pos p1_str val (see Note #3a1B2).*/
  790. }
  791. p1_str_cmp = p1_str;
  792. p2_str_cmp = p2_str;
  793. p1_str_cmp_next = p1_str_cmp;
  794. p2_str_cmp_next = p2_str_cmp;
  795. p1_str_cmp_next++;
  796. p2_str_cmp_next++;
  797. cmp_len = 0u;
  798. while ((*p1_str_cmp == *p2_str_cmp) && /* Cmp strs until non-matching chars (see Note #3c) ... */
  799. (*p1_str_cmp != ( CPU_CHAR )'\0') && /* ... or NULL chars (see Note #3b) ... */
  800. ( p1_str_cmp_next != (const CPU_CHAR *) 0 ) && /* ... or NULL ptr(s) found (see Note #3a2). */
  801. ( p2_str_cmp_next != (const CPU_CHAR *) 0 ) &&
  802. ( cmp_len < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars cmp'd (see Note #3d2). */
  803. p1_str_cmp++;
  804. p2_str_cmp++;
  805. p1_str_cmp_next++;
  806. p2_str_cmp_next++;
  807. cmp_len++;
  808. }
  809. if (cmp_len == len_max) { /* If strs identical for max len nbr of chars, ... */
  810. return (0); /* ... rtn 0 (see Note #3d2A). */
  811. }
  812. if (*p1_str_cmp != *p2_str_cmp) { /* If strs NOT identical, ... */
  813. /* ... calc & rtn char diff (see Note #3c1). */
  814. cmp_val = (CPU_INT16S)((CPU_INT16S)(*p1_str_cmp) - (CPU_INT16S)(*p2_str_cmp));
  815. } else if (*p1_str_cmp == (CPU_CHAR)'\0') { /* If NULL char(s) found, ... */
  816. cmp_val = (CPU_INT16S)0; /* ... strs identical; rtn 0 (see Note #3b). */
  817. } else {
  818. if (p1_str_cmp_next == (const CPU_CHAR *)0) {
  819. if (p2_str_cmp_next == (const CPU_CHAR *)0) { /* If BOTH next str ptrs NULL, ... */
  820. cmp_val = (CPU_INT16S)0; /* ... rtn 0 (see Note #3a2A). */
  821. } else { /* If p1_str_cmp_next NULL, ... */
  822. /* ... rtn neg p2_str_cmp_next val (see Note #3a2B1). */
  823. cmp_val = (CPU_INT16S)((CPU_INT16S)0 - (CPU_INT16S)(*p2_str_cmp_next));
  824. }
  825. } else { /* If p2_str_cmp_next NULL, ... */
  826. cmp_val = (CPU_INT16S)(*p1_str_cmp_next); /* ... rtn pos p1_str_cmp_next val (see Note #3a2B2). */
  827. }
  828. }
  829. return (cmp_val);
  830. }
  831. /*
  832. *********************************************************************************************************
  833. * Str_CmpIgnoreCase()
  834. *
  835. * Description : Determine if two strings are identical, ignoring case.
  836. *
  837. * Argument(s) : p1_str Pointer to first string (see Note #1).
  838. *
  839. * p2_str Pointer to second string (see Note #1).
  840. *
  841. * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, & #3b).
  842. *
  843. * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
  844. *
  845. * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
  846. *
  847. * See also Note #2b.
  848. *
  849. * Caller(s) : Application.
  850. *
  851. * Note(s) : (1) String buffers NOT modified.
  852. *
  853. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcasecmp() : DESCRIPTION' states that :
  854. *
  855. * (1) (A) "The strcasecmp() function shall compare ... the string pointed to by 's1'
  856. * ('p1_str') to the string pointed to by 's2' ('p2_str')" ...
  857. * (B) "ignoring differences in case".
  858. *
  859. * (2) "strcasecmp() ... shall behave as if the strings had been converted to lowercase
  860. * and then a byte comparison performed."
  861. *
  862. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strcasecmp() : RETURN VALUE' states that
  863. * "upon successful completion, strcasecmp() shall return an integer greater than,
  864. * equal to, or less than 0".
  865. *
  866. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
  867. * sign of a non-zero return value shall be determined by the sign of the difference
  868. * between the values of the first pair of bytes ... that differ in the strings
  869. * being compared".
  870. *
  871. * (3) String comparison terminates when :
  872. *
  873. * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
  874. * (1) NULL strings identical; 0 returned.
  875. *
  876. * (B) (1) 'p1_str' passed a NULL pointer.
  877. * (a) Return negative value of character pointed to by 'p2_str', converted
  878. * to lower case (see Note #2a2).
  879. *
  880. * (2) 'p2_str' passed a NULL pointer.
  881. * (a) Return positive value of character pointed to by 'p1_str', converted
  882. * to lower case (see Note #2a2).
  883. *
  884. * (2) (A) BOTH strings point to NULL.
  885. * (1) Strings overlap with NULL address.
  886. * (2) Strings identical up to but NOT beyond or including the NULL address;
  887. * 0 returned.
  888. *
  889. * (B) (1) 'p1_str_cmp_next' points to NULL.
  890. * (a) 'p1_str' overlaps with NULL address.
  891. * (b) Strings compared up to but NOT beyond or including the NULL address.
  892. * (c) Return negative value of character pointed to by 'p2_str_cmp_next',
  893. * converted to lower case (see Note #2a2).
  894. *
  895. * (2) 'p2_str_cmp_next' points to NULL.
  896. * (a) 'p2_str' overlaps with NULL address.
  897. * (b) Strings compared up to but NOT beyond or including the NULL address.
  898. * (c) Return positive value of character pointed to by 'p1_str_cmp_next',
  899. * converted to lower case (see Note #2a2).
  900. *
  901. * (b) Terminating NULL character found in both strings.
  902. * (1) Strings identical; 0 returned.
  903. * (2) Only one NULL character test required in conditional since previous condition
  904. * tested character equality.
  905. *
  906. * (c) Non-matching characters found.
  907. * (1) Return signed-integer difference of the character pointed to by 'p2_str',
  908. * converted to lower case, from the character pointed to by 'p1_str', converted
  909. * to lower case.
  910. *
  911. * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
  912. * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
  913. *********************************************************************************************************
  914. */
  915. CPU_INT16S Str_CmpIgnoreCase (const CPU_CHAR *p1_str,
  916. const CPU_CHAR *p2_str)
  917. {
  918. CPU_INT16S cmp_val;
  919. cmp_val = Str_CmpIgnoreCase_N(p1_str,
  920. p2_str,
  921. DEF_INT_CPU_U_MAX_VAL);
  922. return (cmp_val);
  923. }
  924. /*
  925. *********************************************************************************************************
  926. * Str_CmpIgnoreCase_N()
  927. *
  928. * Description : Determine if two strings are identical for up to a maximum number of characters,
  929. * ignoring case.
  930. *
  931. * Argument(s) : p1_str Pointer to first string (see Note #1).
  932. *
  933. * p2_str Pointer to second string (see Note #1).
  934. *
  935. * len_max Maximum number of characters to compare (see Note #3d).
  936. *
  937. * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, #3b, & #3d).
  938. *
  939. * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
  940. *
  941. * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
  942. *
  943. * See also Note #2b.
  944. *
  945. * Caller(s) : Application.
  946. *
  947. * Note(s) : (1) String buffers NOT modified.
  948. *
  949. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncasecmp() : DESCRIPTION' states that :
  950. *
  951. * (1) (A) "The strncasecmp() function shall compare ... the string pointed to by 's1'
  952. * ('p1_str') to the string pointed to by 's2' ('p2_str')" ...
  953. * (B) "ignoring differences in case" ...
  954. * (C) but "not more than 'n' ('len_max') bytes" of either string.
  955. *
  956. * (2) "strncasecmp() shall behave as if the strings had been converted to lowercase
  957. * and then a byte comparison performed."
  958. *
  959. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncasecmp() : RETURN VALUE' states that
  960. * "upon successful completion, strncasecmp() shall return an integer greater than,
  961. * equal to, or less than 0".
  962. *
  963. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
  964. * sign of a non-zero return value shall be determined by the sign of the difference
  965. * between the values of the first pair of bytes ... that differ in the strings
  966. * being compared".
  967. *
  968. * (3) String comparison terminates when :
  969. *
  970. * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
  971. * (1) NULL strings identical; 0 returned.
  972. *
  973. * (B) (1) 'p1_str' passed a NULL pointer.
  974. * (a) Return negative value of character pointed to by 'p2_str', converted
  975. * to lower case (see Note #2a2).
  976. *
  977. * (2) 'p2_str' passed a NULL pointer.
  978. * (a) Return positive value of character pointed to by 'p1_str', converted
  979. * to lower case (see Note #2a2).
  980. *
  981. * (2) (A) BOTH strings point to NULL.
  982. * (1) Strings overlap with NULL address.
  983. * (2) Strings identical up to but NOT beyond or including the NULL address;
  984. * 0 returned.
  985. *
  986. * (B) (1) 'p1_str_cmp_next' points to NULL.
  987. * (a) 'p1_str' overlaps with NULL address.
  988. * (b) Strings compared up to but NOT beyond or including the NULL address.
  989. * (c) Return negative value of character pointed to by 'p2_str_cmp_next',
  990. * converted to lower case (see Note #2a2).
  991. *
  992. * (2) 'p2_str_cmp_next' points to NULL.
  993. * (a) 'p2_str' overlaps with NULL address.
  994. * (b) Strings compared up to but NOT beyond or including the NULL address.
  995. * (c) Return positive value of character pointed to by 'p1_str_cmp_next',
  996. * converted to lower case (see Note #2a2).
  997. *
  998. * (b) Terminating NULL character found in both strings.
  999. * (1) Strings identical; 0 returned.
  1000. * (2) Only one NULL character test required in conditional since previous condition
  1001. * tested character equality.
  1002. *
  1003. * (c) Non-matching characters found.
  1004. * (1) Return signed-integer difference of the character pointed to by 'p2_str',
  1005. * converted to lower case, from the character pointed to by 'p1_str', converted
  1006. * to lower case.
  1007. *
  1008. * (d) (1) 'len_max' passed a zero length.
  1009. * (A) Zero-length strings identical; 0 returned.
  1010. *
  1011. * (2) First 'len_max' number of characters identical.
  1012. * (A) Strings identical; 0 returned.
  1013. *
  1014. * See also Note #2a1C.
  1015. *
  1016. * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
  1017. * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
  1018. *********************************************************************************************************
  1019. */
  1020. CPU_INT16S Str_CmpIgnoreCase_N (const CPU_CHAR *p1_str,
  1021. const CPU_CHAR *p2_str,
  1022. CPU_SIZE_T len_max)
  1023. {
  1024. const CPU_CHAR *p1_str_cmp;
  1025. const CPU_CHAR *p2_str_cmp;
  1026. const CPU_CHAR *p1_str_cmp_next;
  1027. const CPU_CHAR *p2_str_cmp_next;
  1028. CPU_CHAR char_1;
  1029. CPU_CHAR char_2;
  1030. CPU_INT16S cmp_val;
  1031. CPU_SIZE_T cmp_len;
  1032. if (len_max < 1) { /* If cmp len = 0, rtn 0 (see Note #3d1A). */
  1033. return (0);
  1034. }
  1035. if (p1_str == (const CPU_CHAR *)0) {
  1036. if (p2_str == (const CPU_CHAR *)0) {
  1037. return (0); /* If BOTH str ptrs NULL, rtn 0 (see Note #3a1A). */
  1038. }
  1039. char_2 = ASCII_ToLower(*p2_str);
  1040. cmp_val = (CPU_INT16S)((CPU_INT16S)0 - (CPU_INT16S)char_2);
  1041. return (cmp_val); /* If p1_str NULL, rtn neg p2_str val (see Note #3a1B1).*/
  1042. }
  1043. if (p2_str == (const CPU_CHAR *)0) {
  1044. char_1 = ASCII_ToLower(*p1_str);
  1045. cmp_val = (CPU_INT16S)char_1;
  1046. return (cmp_val); /* If p2_str NULL, rtn pos p1_str val (see Note #3a1B2).*/
  1047. }
  1048. p1_str_cmp = p1_str;
  1049. p2_str_cmp = p2_str;
  1050. p1_str_cmp_next = p1_str_cmp;
  1051. p2_str_cmp_next = p2_str_cmp;
  1052. p1_str_cmp_next++;
  1053. p2_str_cmp_next++;
  1054. char_1 = ASCII_ToLower(*p1_str_cmp);
  1055. char_2 = ASCII_ToLower(*p2_str_cmp);
  1056. cmp_len = 0u;
  1057. while (( char_1 == char_2) && /* Cmp strs until non-matching chars (see Note #3c) ... */
  1058. (*p1_str_cmp != ( CPU_CHAR )'\0') && /* ... or NULL chars (see Note #3b) ... */
  1059. ( p1_str_cmp_next != (const CPU_CHAR *) 0 ) && /* ... or NULL ptr(s) found (see Note #3a2). */
  1060. ( p2_str_cmp_next != (const CPU_CHAR *) 0 ) &&
  1061. ( cmp_len < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars cmp'd (see Note #3d2). */
  1062. p1_str_cmp++;
  1063. p2_str_cmp++;
  1064. p1_str_cmp_next++;
  1065. p2_str_cmp_next++;
  1066. cmp_len++;
  1067. char_1 = ASCII_ToLower(*p1_str_cmp);
  1068. char_2 = ASCII_ToLower(*p2_str_cmp);
  1069. }
  1070. if (cmp_len == len_max) { /* If strs identical for max len nbr of chars, ... */
  1071. return (0); /* ... rtn 0 (see Note #3d2A). */
  1072. }
  1073. if (char_1 != char_2) { /* If strs NOT identical, ... */
  1074. /* ... calc & rtn char diff (see Note #3c1). */
  1075. cmp_val = (CPU_INT16S)((CPU_INT16S)char_1 - (CPU_INT16S)char_2);
  1076. } else if (char_1 == (CPU_CHAR)'\0') { /* If NULL char(s) found, ... */
  1077. cmp_val = (CPU_INT16S)0; /* ... strs identical; rtn 0 (see Note #3b). */
  1078. } else {
  1079. if (p1_str_cmp_next == (const CPU_CHAR *)0) {
  1080. if (p2_str_cmp_next == (const CPU_CHAR *)0) { /* If BOTH next str ptrs NULL, ... */
  1081. cmp_val = (CPU_INT16S)0; /* ... rtn 0 (see Note #3a2A). */
  1082. } else { /* If p1_str_cmp_next NULL, ... */
  1083. char_2 = ASCII_ToLower(*p2_str_cmp_next);
  1084. /* ... rtn neg p2_str_cmp_next val (see Note #3a2B1). */
  1085. cmp_val = (CPU_INT16S)((CPU_INT16S)0 - (CPU_INT16S)char_2);
  1086. }
  1087. } else { /* If p2_str_cmp_next NULL, ... */
  1088. char_1 = ASCII_ToLower(*p1_str_cmp_next);
  1089. cmp_val = (CPU_INT16S)char_1; /* ... rtn pos p1_str_cmp_next val (see Note #3a2B2). */
  1090. }
  1091. }
  1092. return (cmp_val);
  1093. }
  1094. /*
  1095. *********************************************************************************************************
  1096. * Str_Char()
  1097. *
  1098. * Description : Search string for first occurrence of specific character.
  1099. *
  1100. * Argument(s) : pstr Pointer to string (see Note #1).
  1101. *
  1102. * srch_char Search character.
  1103. *
  1104. * Return(s) : Pointer to first occurrence of search character in string, if any (see Note #2b1).
  1105. *
  1106. * Pointer to NULL, otherwise (see Note #2b2).
  1107. *
  1108. * Caller(s) : Application.
  1109. *
  1110. * Note(s) : (1) String buffer NOT modified.
  1111. *
  1112. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : DESCRIPTION' states that :
  1113. *
  1114. * (1) "The strchr() function shall locate the first occurrence of 'c' ('srch_char')
  1115. * ... in the string pointed to by 's' ('pstr')."
  1116. * (2) "The terminating null byte is considered to be part of the string."
  1117. *
  1118. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : RETURN VALUE' states that
  1119. * "upon completion, strchr() shall return" :
  1120. *
  1121. * (1) "a pointer to the byte," ...
  1122. * (2) "or a null pointer if the byte was not found."
  1123. * (A) #### Although NO strchr() specification states to return NULL for
  1124. * any other reason(s), NULL is also returned for any error(s).
  1125. *
  1126. * (3) String search terminates when :
  1127. *
  1128. * (a) String pointer passed a NULL pointer.
  1129. * (1) No string search performed; NULL pointer returned.
  1130. *
  1131. * (b) String pointer points to NULL.
  1132. * (1) String overlaps with NULL address; NULL pointer returned.
  1133. *
  1134. * (c) String's terminating NULL character found.
  1135. * (1) Search character NOT found in search string; NULL pointer returned
  1136. * (see Note #2b2).
  1137. * (2) Applicable even if search character is the terminating NULL character
  1138. * (see Note #2a2).
  1139. *
  1140. * (d) Search character found.
  1141. * (1) Return pointer to first occurrence of search character in search string
  1142. * (see Note #2a1).
  1143. *********************************************************************************************************
  1144. */
  1145. CPU_CHAR *Str_Char (const CPU_CHAR *pstr,
  1146. CPU_CHAR srch_char)
  1147. {
  1148. CPU_CHAR *pstr_rtn;
  1149. pstr_rtn = Str_Char_N(pstr,
  1150. DEF_INT_CPU_U_MAX_VAL,
  1151. srch_char);
  1152. return (pstr_rtn);
  1153. }
  1154. /*
  1155. *********************************************************************************************************
  1156. * Str_Char_N()
  1157. *
  1158. * Description : Search string for first occurrence of specific character, up to a maximum number
  1159. * of characters.
  1160. *
  1161. * Argument(s) : pstr Pointer to string (see Note #1).
  1162. *
  1163. * len_max Maximum number of characters to search (see Notes #2c & #3e).
  1164. *
  1165. * srch_char Search character.
  1166. *
  1167. * Return(s) : Pointer to first occurrence of search character in string, if any (see Note #2b1).
  1168. *
  1169. * Pointer to NULL, otherwise (see Note #2b2).
  1170. *
  1171. * Caller(s) : Application.
  1172. *
  1173. * Note(s) : (1) String buffer NOT modified.
  1174. *
  1175. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : DESCRIPTION' states that :
  1176. *
  1177. * (1) "The strchr() function shall locate the first occurrence of 'c' ('srch_char')
  1178. * ... in the string pointed to by 's' ('pstr')."
  1179. * (2) "The terminating null byte is considered to be part of the string."
  1180. *
  1181. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strchr() : RETURN VALUE' states that
  1182. * "upon completion, strchr() shall return" :
  1183. *
  1184. * (1) "a pointer to the byte," ...
  1185. * (2) "or a null pointer if the byte was not found."
  1186. * (A) #### Although NO strchr() specification states to return NULL for
  1187. * any other reason(s), NULL is also returned for any error(s).
  1188. *
  1189. * (c) Ideally, the 'len_max' argument would be the last argument in this function's
  1190. * argument list for consistency with all other custom string library functions.
  1191. * However, the 'len_max' argument is sequentially ordered as the second argument
  1192. * to comply with most standard library's strnchr() argument list.
  1193. *
  1194. * (3) String search terminates when :
  1195. *
  1196. * (a) String pointer passed a NULL pointer.
  1197. * (1) No string search performed; NULL pointer returned.
  1198. *
  1199. * (b) String pointer points to NULL.
  1200. * (1) String overlaps with NULL address; NULL pointer returned.
  1201. *
  1202. * (c) String's terminating NULL character found.
  1203. * (1) Search character NOT found in search string; NULL pointer returned
  1204. * (see Note #2b2).
  1205. * (2) Applicable even if search character is the terminating NULL character
  1206. * (see Note #2a2).
  1207. *
  1208. * (d) Search character found.
  1209. * (1) Return pointer to first occurrence of search character in search string
  1210. * (see Note #2a1).
  1211. *
  1212. * (e) 'len_max' number of characters searched.
  1213. * (1) Search character NOT found in search string within first 'len_max' number
  1214. * of characters; NULL pointer returned.
  1215. * (2) 'len_max' number of characters MAY include terminating NULL character
  1216. * (see Note #2a2).
  1217. *********************************************************************************************************
  1218. */
  1219. CPU_CHAR *Str_Char_N (const CPU_CHAR *pstr,
  1220. CPU_SIZE_T len_max,
  1221. CPU_CHAR srch_char)
  1222. {
  1223. const CPU_CHAR *pstr_char;
  1224. CPU_SIZE_T len_srch;
  1225. if (pstr == (const CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #3a1). */
  1226. return ((CPU_CHAR *)0);
  1227. }
  1228. if (len_max < 1) { /* Rtn NULL if srch len = 0 (see Note #3e1). */
  1229. return ((CPU_CHAR *)0);
  1230. }
  1231. pstr_char = pstr;
  1232. len_srch = 0u;
  1233. while (( pstr_char != (const CPU_CHAR *) 0 ) && /* Srch str until NULL ptr [see Note #3b] ... */
  1234. (*pstr_char != ( CPU_CHAR )'\0') && /* ... or NULL char (see Note #3c) ... */
  1235. (*pstr_char != ( CPU_CHAR )srch_char) && /* ... or srch char found (see Note #3d); ... */
  1236. ( len_srch < ( CPU_SIZE_T)len_max)) { /* ... or max nbr chars srch'd (see Note #3e). */
  1237. pstr_char++;
  1238. len_srch++;
  1239. }
  1240. if (pstr_char == (const CPU_CHAR *)0) { /* Rtn NULL if NULL ptr found (see Note #3b1). */
  1241. return ((CPU_CHAR *)0);
  1242. }
  1243. if (len_srch >= len_max) { /* Rtn NULL if srch char NOT found ... */
  1244. return ((CPU_CHAR *)0); /* ... within max nbr of chars (see Note #3e1). */
  1245. }
  1246. if (*pstr_char != srch_char) { /* Rtn NULL if srch char NOT found (see Note #3c1). */
  1247. return ((CPU_CHAR *)0);
  1248. }
  1249. return ((CPU_CHAR *)pstr_char); /* Else rtn ptr to found srch char (see Note #3d1). */
  1250. }
  1251. /*
  1252. *********************************************************************************************************
  1253. * Str_Char_Last()
  1254. *
  1255. * Description : Search string for last occurrence of specific character.
  1256. *
  1257. * Argument(s) : pstr Pointer to string (see Note #1).
  1258. *
  1259. * srch_char Search character.
  1260. *
  1261. * Return(s) : Pointer to last occurrence of search character in string, if any (see Note #2b1).
  1262. *
  1263. * Pointer to NULL, otherwise (see Note #2b2).
  1264. *
  1265. * Caller(s) : Application.
  1266. *
  1267. * Note(s) : (1) String buffer NOT modified.
  1268. *
  1269. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : DESCRIPTION' states that :
  1270. *
  1271. * (1) "The strrchr() function shall locate the last occurrence of 'c' ('srch_char')
  1272. * ... in the string pointed to by 's' ('pstr')."
  1273. * (2) "The terminating null byte is considered to be part of the string."
  1274. *
  1275. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : RETURN VALUE' states that
  1276. * "upon successful completion, strrchr() shall return" :
  1277. *
  1278. * (1) "a pointer to the byte" ...
  1279. * (2) "or a null pointer if 'c' ('srch_char') does not occur in the string."
  1280. * (A) #### Although NO strrchr() specification states to return NULL for
  1281. * any other reason(s), NULL is also returned for any error(s).
  1282. *
  1283. * (3) String search terminates when :
  1284. *
  1285. * (a) String pointer passed a NULL pointer.
  1286. * (1) No string search performed; NULL pointer returned.
  1287. *
  1288. * (b) String pointer points to NULL.
  1289. * (1) String overlaps with NULL address; NULL pointer returned.
  1290. *
  1291. * (c) String searched from end to beginning.
  1292. * (1) Search character NOT found in search string; NULL pointer returned.
  1293. * (2) Applicable even if search character is the terminating NULL character
  1294. * (see Note #2a2).
  1295. *
  1296. * (d) Search character found.
  1297. * (1) Return pointer to last occurrence of search character in search string
  1298. * (see Note #2a1).
  1299. *********************************************************************************************************
  1300. */
  1301. CPU_CHAR *Str_Char_Last (const CPU_CHAR *pstr,
  1302. CPU_CHAR srch_char)
  1303. {
  1304. CPU_CHAR *pstr_rtn;
  1305. pstr_rtn = Str_Char_Last_N(pstr,
  1306. DEF_INT_CPU_U_MAX_VAL,
  1307. srch_char);
  1308. return (pstr_rtn);
  1309. }
  1310. /*
  1311. *********************************************************************************************************
  1312. * Str_Char_Last_N()
  1313. *
  1314. * Description : Search string for last occurrence of specific character, up to a maximum number
  1315. * of characters.
  1316. *
  1317. * Argument(s) : pstr Pointer to string (see Note #1).
  1318. *
  1319. * len_max Maximum number of characters to search (see Notes #2c & #3e).
  1320. *
  1321. * srch_char Search character.
  1322. *
  1323. * Return(s) : Pointer to last occurrence of search character in string, if any (see Note #2b1).
  1324. *
  1325. * Pointer to NULL, otherwise (see Note #2b2).
  1326. *
  1327. * Caller(s) : Application.
  1328. *
  1329. * Note(s) : (1) String buffer NOT modified.
  1330. *
  1331. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : DESCRIPTION' states that :
  1332. *
  1333. * (1) "The strrchr() function shall locate the last occurrence of 'c' ('srch_char')
  1334. * ... in the string pointed to by 's' ('pstr')."
  1335. * (2) "The terminating null byte is considered to be part of the string."
  1336. *
  1337. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strrchr() : RETURN VALUE' states that
  1338. * "upon successful completion, strrchr() shall return" :
  1339. *
  1340. * (1) "a pointer to the byte" ...
  1341. * (2) "or a null pointer if 'c' ('srch_char') does not occur in the string."
  1342. * (A) #### Although NO strrchr() specification states to return NULL for
  1343. * any other reason(s), NULL is also returned for any error(s).
  1344. *
  1345. * (c) Ideally, the 'len_max' argument would be the last argument in this function's
  1346. * argument list for consistency with all other custom string library functions.
  1347. * However, the 'len_max' argument is sequentially ordered as the second argument
  1348. * to comply with most standard library's strnrchr() argument list.
  1349. *
  1350. * See also 'Str_Char_N() Note #2c'.
  1351. *
  1352. * (3) String search terminates when :
  1353. *
  1354. * (a) String pointer passed a NULL pointer.
  1355. * (1) No string search performed; NULL pointer returned.
  1356. *
  1357. * (b) String pointer points to NULL.
  1358. * (1) String overlaps with NULL address; NULL pointer returned.
  1359. *
  1360. * (c) String searched from end to beginning.
  1361. * (1) Search character NOT found in search string; NULL pointer returned
  1362. * (see Note #2b2).
  1363. * (2) Applicable even if search character is the terminating NULL character
  1364. * (see Note #2a2).
  1365. *
  1366. * (d) Search character found.
  1367. * (1) Return pointer to last occurrence of search character in search string
  1368. * (see Note #2a1).
  1369. *
  1370. * (e) 'len_max' number of characters searched.
  1371. * (1) Search character NOT found in search string within last 'len_max' number
  1372. * of characters; NULL pointer returned.
  1373. * (2) 'len_max' number of characters MAY include terminating NULL character
  1374. * (see Note #2a2).
  1375. *********************************************************************************************************
  1376. */
  1377. CPU_CHAR *Str_Char_Last_N (const CPU_CHAR *pstr,
  1378. CPU_SIZE_T len_max,
  1379. CPU_CHAR srch_char)
  1380. {
  1381. const CPU_CHAR *pstr_char;
  1382. CPU_SIZE_T str_len_max;
  1383. CPU_SIZE_T str_len;
  1384. if (pstr == (const CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #3a1). */
  1385. return ((CPU_CHAR *)0);
  1386. }
  1387. if (len_max < 1) { /* Rtn NULL if srch len = 0 (see Note #3e1). */
  1388. return ((CPU_CHAR *)0);
  1389. }
  1390. pstr_char = pstr;
  1391. str_len_max = len_max - sizeof(""); /* Str len adj'd for NULL char len. */
  1392. str_len = Str_Len_N(pstr_char, str_len_max);
  1393. pstr_char += str_len;
  1394. if (pstr_char == (const CPU_CHAR *)0) { /* Rtn NULL if NULL ptr found (see Note #3b1). */
  1395. return ((CPU_CHAR *)0);
  1396. }
  1397. while (( pstr_char != pstr) && /* Srch str from end until beginning (see Note #3c) ... */
  1398. (*pstr_char != srch_char)) { /* ... until srch char found (see Note #3d). */
  1399. pstr_char--;
  1400. }
  1401. if (*pstr_char != srch_char) { /* Rtn NULL if srch char NOT found (see Note #3c1). */
  1402. return ((CPU_CHAR *)0);
  1403. }
  1404. return ((CPU_CHAR *)pstr_char); /* Else rtn ptr to found srch char (see Note #3d1). */
  1405. }
  1406. /*
  1407. *********************************************************************************************************
  1408. * Str_Char_Replace()
  1409. *
  1410. * Description : Search string for specific character and replace it by another specific character.
  1411. *
  1412. * Argument(s) : pstr Pointer to string (see Note #1).
  1413. *
  1414. * char_srch Search character.
  1415. *
  1416. * char_replace Replace character.
  1417. *
  1418. * Return(s) : Pointer to string, if NO error(s).
  1419. *
  1420. * Pointer to NULL, otherwise.
  1421. *
  1422. * Caller(s) : Application.
  1423. *
  1424. * Note(s) : (1) String buffer modified.
  1425. *
  1426. * (2) String search terminates when :
  1427. *
  1428. * (a) String pointer passed a NULL pointer.
  1429. * (1) No string search performed; NULL pointer returned.
  1430. *
  1431. * (b) String pointer points to NULL.
  1432. * (1) String overlaps with NULL address; NULL pointer returned.
  1433. *
  1434. * (c) String's terminating NULL character found.
  1435. * (1) Search character NOT found in search string; NULL pointer returned
  1436. * (2) Applicable even if search character is the terminating NULL character
  1437. *
  1438. * (d) Search character found.
  1439. * (1) Replace character found by the specified character.
  1440. *********************************************************************************************************
  1441. */
  1442. CPU_CHAR *Str_Char_Replace (CPU_CHAR *pstr,
  1443. CPU_CHAR char_srch,
  1444. CPU_CHAR char_replace)
  1445. {
  1446. CPU_CHAR *pstr_rtn;
  1447. pstr_rtn = Str_Char_Replace_N(pstr,
  1448. char_srch,
  1449. char_replace,
  1450. DEF_INT_CPU_U_MAX_VAL);
  1451. return (pstr_rtn);
  1452. }
  1453. /*
  1454. *********************************************************************************************************
  1455. * Str_Char_Replace_N()
  1456. *
  1457. * Description : Search string for specific character and replace it by another specific character, up to
  1458. * a maximum number of characters.
  1459. *
  1460. * Argument(s) : pstr Pointer to string (see Note #1).
  1461. *
  1462. * char_srch Search character.
  1463. *
  1464. * char_replace Replace character.
  1465. *
  1466. * len_max Maximum number of characters to search (see Notes #2c & #3e).
  1467. *
  1468. * Return(s) : Pointer to string, if NO error(s).
  1469. *
  1470. * Pointer to NULL, otherwise.
  1471. *
  1472. * Caller(s) : Application.
  1473. *
  1474. * Note(s) : (1) String buffer modified.
  1475. *
  1476. * (2) String search terminates when :
  1477. *
  1478. * (a) String pointer passed a NULL pointer.
  1479. * (1) No string search performed; NULL pointer returned.
  1480. *
  1481. * (b) String pointer points to NULL.
  1482. * (1) String overlaps with NULL address; NULL pointer returned.
  1483. *
  1484. * (c) String's terminating NULL character found.
  1485. * (1) Search character NOT found in search string; NULL pointer returned
  1486. * (2) Applicable even if search character is the terminating NULL character
  1487. *
  1488. * (d) Search character found.
  1489. * (1) Replace character found by the specified character.
  1490. *
  1491. * (e) 'len_max' number of characters searched.
  1492. * (1) Search character NOT found in search string within first 'len_max' number
  1493. * of characters; NULL pointer returned.
  1494. * (2) 'len_max' number of characters MAY include terminating NULL character
  1495. * (see Note #2a2).
  1496. *********************************************************************************************************
  1497. */
  1498. CPU_CHAR *Str_Char_Replace_N (CPU_CHAR *pstr,
  1499. CPU_CHAR char_srch,
  1500. CPU_CHAR char_replace,
  1501. CPU_SIZE_T len_max)
  1502. {
  1503. CPU_CHAR *pstr_char;
  1504. CPU_SIZE_T len;
  1505. if (pstr == (const CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #2a1). */
  1506. return ((CPU_CHAR *)0);
  1507. }
  1508. if (len_max < 1) { /* Rtn NULL if srch len = 0 (see Note #2e1). */
  1509. return ((CPU_CHAR *)0);
  1510. }
  1511. pstr_char = pstr;
  1512. len = len_max;
  1513. while (( pstr_char != (const CPU_CHAR *)0) && /* Srch str until NULL ptr [see Note #2b] ... */
  1514. (*pstr_char != ASCII_CHAR_NULL ) && /* ... or NULL char (see Note #2c) ... */
  1515. ( len > 0)) { /* ... or max nbr chars srch'd (see Note #2e). */
  1516. if (*pstr_char == char_srch) {
  1517. *pstr_char = char_replace; /* Replace char if srch char is found. */
  1518. }
  1519. pstr_char++;
  1520. len--;
  1521. }
  1522. return (pstr);
  1523. }
  1524. /*
  1525. *********************************************************************************************************
  1526. * Str_Str()
  1527. *
  1528. * Description : Search string for first occurence of a specific search string.
  1529. *
  1530. * Argument(s) : pstr Pointer to string (see Note #1).
  1531. *
  1532. * pstr_srch Pointer to search string (see Note #1).
  1533. *
  1534. * Return(s) : Pointer to first occurrence of search string in string, if any (see Note #2b1A).
  1535. *
  1536. * Pointer to string, if NULL search string (see Note #2b2).
  1537. *
  1538. * Pointer to NULL, otherwise (see Note #2b1B).
  1539. *
  1540. * Caller(s) : Application.
  1541. *
  1542. * Note(s) : (1) String buffers NOT modified.
  1543. *
  1544. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : DESCRIPTION' states that :
  1545. *
  1546. * (1) "The strstr() function shall locate the first occurrence in the string
  1547. * pointed to by 's1' ('pstr') of the sequence of bytes ... in the string
  1548. * pointed to by 's2' ('pstr_srch')" ...
  1549. * (2) "(excluding the terminating null byte)."
  1550. *
  1551. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : RETURN VALUE' states that :
  1552. *
  1553. * (1) "Upon successful completion, strstr() shall return" :
  1554. * (A) "a pointer to the located string" ...
  1555. * (B) "or a null pointer if the string is not found."
  1556. * (1) #### Although NO strstr() specification states to return NULL for
  1557. * any other reason(s), NULL is also returned for any error(s).
  1558. *
  1559. * (2) "If 's2' ('pstr_srch') points to a string with zero length, the function
  1560. * shall return 's1' ('pstr')."
  1561. *
  1562. * (3) String search terminates when :
  1563. *
  1564. * (a) String pointer(s) are passed NULL pointers.
  1565. * (1) No string search performed; NULL pointer returned.
  1566. *
  1567. * (b) String pointer(s) point to NULL.
  1568. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  1569. *
  1570. * (c) Search string length equal to zero.
  1571. * (1) No string search performed; string pointer returned (see Note #2b2).
  1572. *
  1573. * (d) Search string length greater than string length.
  1574. * (1) No string search performed; NULL pointer returned (see Note #2b1B).
  1575. *
  1576. * (e) Entire string has been searched.
  1577. * (1) Search string not found; NULL pointer returned (see Note #2b1B).
  1578. *
  1579. * (f) Search string found.
  1580. * (1) Return pointer to first occurrence of search string in string (see Note #2b1A).
  1581. *********************************************************************************************************
  1582. */
  1583. CPU_CHAR *Str_Str (const CPU_CHAR *pstr,
  1584. const CPU_CHAR *pstr_srch)
  1585. {
  1586. CPU_CHAR *pstr_rtn;
  1587. pstr_rtn = Str_Str_N(pstr,
  1588. pstr_srch,
  1589. DEF_INT_CPU_U_MAX_VAL);
  1590. return (pstr_rtn);
  1591. }
  1592. /*
  1593. *********************************************************************************************************
  1594. * Str_Str_N()
  1595. *
  1596. * Description : Search string for first occurence of a specific search string, up to a maximum number
  1597. * of characters.
  1598. *
  1599. * Argument(s) : pstr Pointer to string (see Note #1).
  1600. *
  1601. * pstr_srch Pointer to search string (see Note #1).
  1602. *
  1603. * len_max Maximum number of characters to search (see Note #3g).
  1604. *
  1605. * Return(s) : Pointer to first occurrence of search string in string, if any (see Note #2b1A).
  1606. *
  1607. * Pointer to string, if NULL search string (see Note #2b2).
  1608. *
  1609. * Pointer to NULL, otherwise (see Note #2b1B).
  1610. *
  1611. * Caller(s) : Application.
  1612. *
  1613. * Note(s) : (1) String buffers NOT modified.
  1614. *
  1615. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : DESCRIPTION' states that :
  1616. *
  1617. * (1) "The strstr() function shall locate the first occurrence in the string
  1618. * pointed to by 's1' ('pstr') of the sequence of bytes ... in the string
  1619. * pointed to by 's2' ('pstr_srch')" ...
  1620. * (2) "(excluding the terminating null byte)."
  1621. *
  1622. * (b) IEEE Std 1003.1, 2004 Edition, Section 'strstr() : RETURN VALUE' states that :
  1623. *
  1624. * (1) "Upon successful completion, strstr() shall return" :
  1625. * (A) "a pointer to the located string" ...
  1626. * (B) "or a null pointer if the string is not found."
  1627. * (1) #### Although NO strstr() specification states to return NULL for
  1628. * any other reason(s), NULL is also returned for any error(s).
  1629. *
  1630. * (2) "If 's2' ('pstr_srch') points to a string with zero length, the function
  1631. * shall return 's1' ('pstr')."
  1632. *
  1633. * (3) String search terminates when :
  1634. *
  1635. * (a) String pointer(s) are passed NULL pointers.
  1636. * (1) No string search performed; NULL pointer returned.
  1637. *
  1638. * (b) String pointer(s) point to NULL.
  1639. * (1) String buffer(s) overlap with NULL address; NULL pointer returned.
  1640. *
  1641. * (c) Search string length equal to zero.
  1642. * (1) No string search performed; string pointer returned (see Note #2b2).
  1643. *
  1644. * (d) Search string length greater than string length.
  1645. * (1) No string search performed; NULL pointer returned (see Note #2b1B).
  1646. *
  1647. * (e) Entire string has been searched.
  1648. * (1) Search string not found; NULL pointer returned (see Note #2b1B).
  1649. * (2) Maximum size of the search is defined as the subtraction of the
  1650. * search string length from the string length.
  1651. *
  1652. * (f) Search string found.
  1653. * (1) Return pointer to first occurrence of search string in string (see Note #2b1A).
  1654. * (2) Search string found via Str_Cmp_N().
  1655. *
  1656. * (g) 'len_max' number of characters searched.
  1657. * (1) 'len_max' number of characters does NOT include terminating NULL character
  1658. * (see Note #2a2).
  1659. *********************************************************************************************************
  1660. */
  1661. CPU_CHAR *Str_Str_N (const CPU_CHAR *pstr,
  1662. const CPU_CHAR *pstr_srch,
  1663. CPU_SIZE_T len_max)
  1664. {
  1665. CPU_SIZE_T str_len;
  1666. CPU_SIZE_T str_len_srch;
  1667. CPU_SIZE_T len_max_srch;
  1668. CPU_SIZE_T srch_len;
  1669. CPU_SIZE_T srch_ix;
  1670. CPU_BOOLEAN srch_done;
  1671. CPU_INT16S srch_cmp;
  1672. const CPU_CHAR *pstr_str;
  1673. const CPU_CHAR *pstr_srch_ix;
  1674. /* Rtn NULL if str ptr(s) NULL (see Note #3a). */
  1675. if (pstr == (const CPU_CHAR *)0) {
  1676. return ((CPU_CHAR *)0);
  1677. }
  1678. if (pstr_srch == (const CPU_CHAR *)0) {
  1679. return ((CPU_CHAR *)0);
  1680. }
  1681. if (len_max < 1) { /* Rtn NULL if srch len = 0 (see Note #3g). */
  1682. return ((CPU_CHAR *)0);
  1683. }
  1684. /* Lim max srch str len (to chk > str len). */
  1685. len_max_srch = (len_max < DEF_INT_CPU_U_MAX_VAL)
  1686. ? (len_max + 1u) : DEF_INT_CPU_U_MAX_VAL;
  1687. str_len = Str_Len_N(pstr, len_max);
  1688. str_len_srch = Str_Len_N(pstr_srch, len_max_srch);
  1689. if (str_len_srch < 1) { /* Rtn ptr to str if srch str len = 0 (see Note #2b2). */
  1690. return ((CPU_CHAR *)pstr);
  1691. }
  1692. if (str_len_srch > str_len) { /* Rtn NULL if srch str len > str len (see Note #3d). */
  1693. return ((CPU_CHAR *)0);
  1694. }
  1695. /* Rtn NULL if NULL ptr found (see Note #3b1). */
  1696. pstr_str = pstr + str_len;
  1697. if (pstr_str == (const CPU_CHAR *)0) {
  1698. return ((CPU_CHAR *)0);
  1699. }
  1700. pstr_str = pstr_srch + str_len_srch;
  1701. if (pstr_str == (const CPU_CHAR *)0) {
  1702. return ((CPU_CHAR *)0);
  1703. }
  1704. srch_len = str_len - str_len_srch; /* Calc srch len (see Note #3e2). */
  1705. srch_ix = 0u;
  1706. do {
  1707. pstr_srch_ix = (const CPU_CHAR *)(pstr + srch_ix);
  1708. srch_cmp = Str_Cmp_N(pstr_srch_ix, pstr_srch, str_len_srch);
  1709. srch_done = (srch_cmp == 0) ? DEF_YES : DEF_NO;
  1710. srch_ix++;
  1711. } while ((srch_done == DEF_NO) && (srch_ix <= srch_len));
  1712. if (srch_cmp != 0) { /* Rtn NULL if srch str NOT found (see Note #3e2). */
  1713. return ((CPU_CHAR *)0);
  1714. }
  1715. return ((CPU_CHAR *)pstr_srch_ix); /* Else rtn ptr to found srch str (see Note #3f1). */
  1716. }
  1717. /*
  1718. *********************************************************************************************************
  1719. * Str_FmtNbr_Int32U()
  1720. *
  1721. * Description : Format 32-bit unsigned integer into a multi-digit character string.
  1722. *
  1723. * Argument(s) : nbr Number to format.
  1724. *
  1725. * nbr_dig Number of digits to format (see Note #1).
  1726. *
  1727. * The following may be used to specify the number of digits to format :
  1728. *
  1729. * DEF_INT_32U_NBR_DIG_MIN Minimum number of 32-bit unsigned digits
  1730. * DEF_INT_32U_NBR_DIG_MAX Maximum number of 32-bit unsigned digits
  1731. *
  1732. * nbr_base Base of number to format (see Note #2).
  1733. *
  1734. * The following may be used to specify the number base :
  1735. *
  1736. * DEF_NBR_BASE_BIN Base 2
  1737. * DEF_NBR_BASE_OCT Base 8
  1738. * DEF_NBR_BASE_DEC Base 10
  1739. * DEF_NBR_BASE_HEX Base 16
  1740. *
  1741. * lead_char Prepend leading character (see Note #3) :
  1742. *
  1743. * '\0' Do NOT prepend leading character to string.
  1744. * Printable character Prepend leading character to string.
  1745. * Unprintable character Format invalid string (see Note #6).
  1746. *
  1747. * lower_case Format alphabetic characters (if any) in lower case :
  1748. *
  1749. * DEF_NO Format alphabetic characters in upper case.
  1750. * DEF_YES Format alphabetic characters in lower case.
  1751. *
  1752. * nul Append terminating NULL-character (see Note #4) :
  1753. *
  1754. * DEF_NO Do NOT append terminating NULL-character to string.
  1755. * DEF_YES Append terminating NULL-character to string.
  1756. *
  1757. * pstr Pointer to character array to return formatted number string (see Note #5).
  1758. *
  1759. * Return(s) : Pointer to formatted string, if NO error(s).
  1760. *
  1761. * Pointer to NULL, otherwise.
  1762. *
  1763. * Caller(s) : Application.
  1764. *
  1765. * Note(s) : (1) (a) If the number of digits to format ('nbr_dig') is zero; then NO formatting
  1766. * is performed except possible NULL-termination of the string (see Note #4).
  1767. *
  1768. * Example :
  1769. *
  1770. * nbr = 23456
  1771. * nbr_dig = 0
  1772. * nbr_base = 10
  1773. *
  1774. * pstr = "" See Note #6a
  1775. *
  1776. * (b) If the number of digits to format ('nbr_dig') is less than the number of
  1777. * significant integer digits of the number to format ('nbr'); then an invalid
  1778. * string is formatted instead of truncating any significant integer digits.
  1779. *
  1780. * Example :
  1781. *
  1782. * nbr = 23456
  1783. * nbr_dig = 3
  1784. * nbr_base = 10
  1785. *
  1786. * pstr = "???" See Note #6b
  1787. *
  1788. * (2) The number's base MUST be between 2 & 36, inclusive.
  1789. *
  1790. * (3) Leading character option prepends leading characters prior to the first non-zero digit.
  1791. *
  1792. * (a) (1) Leading character MUST be a printable ASCII character.
  1793. *
  1794. * (2) (A) Leading character MUST NOT be a number base digit, ...
  1795. * (B) with the exception of '0'.
  1796. *
  1797. * (b) The number of leading characters is such that the total number of significant
  1798. * integer digits plus the number of leading characters is equal to the requested
  1799. * number of integer digits to format ('nbr_dig').
  1800. *
  1801. * Example :
  1802. *
  1803. * nbr = 23456
  1804. * nbr_dig = 7
  1805. * nbr_base = 10
  1806. * lead_char = ' '
  1807. *
  1808. * pstr = " 23456"
  1809. *
  1810. * (c) (1) If the value of the number to format is zero ...
  1811. * (2) ... & the number of digits to format is non-zero, ...
  1812. * (3) ... but NO leading character available; ...
  1813. * (4) ... then one digit of '0' value is formatted.
  1814. *
  1815. * This is NOT a leading character; but a single integer digit of '0' value.
  1816. *
  1817. * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
  1818. * array formatting.
  1819. *
  1820. * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
  1821. * terminate option DISABLED will cause character string run-on.
  1822. *
  1823. * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
  1824. *
  1825. * (b) To prevent character buffer overrun :
  1826. *
  1827. * Character array size MUST be >= ('nbr_dig' +
  1828. * 1 'NUL' terminator) characters
  1829. *
  1830. * (6) For any unsuccessful string format or error(s), an invalid string of question marks
  1831. * ('?') will be formatted, where the number of question marks is determined by the
  1832. * number of digits to format ('nbr_dig') :
  1833. *
  1834. * Invalid string's { (a) 0 (NULL string) , if 'nbr_dig' = 0
  1835. * number of = {
  1836. * question marks { (b) 'nbr_dig' , if 'nbr_dig' > 0
  1837. *
  1838. *********************************************************************************************************
  1839. */
  1840. CPU_CHAR *Str_FmtNbr_Int32U (CPU_INT32U nbr,
  1841. CPU_INT08U nbr_dig,
  1842. CPU_INT08U nbr_base,
  1843. CPU_CHAR lead_char,
  1844. CPU_BOOLEAN lower_case,
  1845. CPU_BOOLEAN nul,
  1846. CPU_CHAR *pstr)
  1847. {
  1848. CPU_CHAR *pstr_fmt;
  1849. pstr_fmt = Str_FmtNbr_Int32(nbr, /* Fmt unsigned int into str. */
  1850. nbr_dig,
  1851. nbr_base,
  1852. DEF_NO,
  1853. lead_char,
  1854. lower_case,
  1855. nul,
  1856. pstr);
  1857. return (pstr_fmt);
  1858. }
  1859. /*
  1860. *********************************************************************************************************
  1861. * Str_FmtNbr_Int32S()
  1862. *
  1863. * Description : Format 32-bit signed integer into a multi-digit character string.
  1864. *
  1865. * Argument(s) : nbr Number to format.
  1866. *
  1867. * nbr_dig Number of digits to format (see Note #1).
  1868. *
  1869. * The following may be used to specify the number of digits to format :
  1870. *
  1871. * DEF_INT_32S_NBR_DIG_MIN + 1 Minimum number of 32-bit signed digits
  1872. * DEF_INT_32S_NBR_DIG_MAX + 1 Maximum number of 32-bit signed digits
  1873. * (plus 1 digit for possible negative sign)
  1874. *
  1875. * nbr_base Base of number to format (see Note #2).
  1876. *
  1877. * The following may be used to specify the number base :
  1878. *
  1879. * DEF_NBR_BASE_BIN Base 2
  1880. * DEF_NBR_BASE_OCT Base 8
  1881. * DEF_NBR_BASE_DEC Base 10
  1882. * DEF_NBR_BASE_HEX Base 16
  1883. *
  1884. * lead_char Prepend leading character (see Note #3) :
  1885. *
  1886. * '\0' Do NOT prepend leading character to string.
  1887. * Printable character Prepend leading character to string.
  1888. * Unprintable character Format invalid string (see Note #6).
  1889. *
  1890. * lower_case Format alphabetic characters (if any) in lower case :
  1891. *
  1892. * DEF_NO Format alphabetic characters in upper case.
  1893. * DEF_YES Format alphabetic characters in lower case.
  1894. *
  1895. * nul Append terminating NULL-character (see Note #4) :
  1896. *
  1897. * DEF_NO Do NOT append terminating NULL-character to string.
  1898. * DEF_YES Append terminating NULL-character to string.
  1899. *
  1900. * pstr Pointer to character array to return formatted number string (see Note #5).
  1901. *
  1902. * Return(s) : Pointer to formatted string, if NO error(s).
  1903. *
  1904. * Pointer to NULL, otherwise.
  1905. *
  1906. * Caller(s) : Application.
  1907. *
  1908. * Note(s) : (1) (a) If the number of digits to format ('nbr_dig') is zero; then NO formatting
  1909. * is performed except possible NULL-termination of the string (see Note #4).
  1910. *
  1911. * Example :
  1912. *
  1913. * nbr = -23456
  1914. * nbr_dig = 0
  1915. * nbr_base = 10
  1916. *
  1917. * pstr = "" See Note #6a
  1918. *
  1919. * (b) If the number of digits to format ('nbr_dig') is less than the number of
  1920. * significant integer digits of the number to format ('nbr'); then an invalid
  1921. * string is formatted instead of truncating any significant integer digits.
  1922. *
  1923. * Example :
  1924. *
  1925. * nbr = 23456
  1926. * nbr_dig = 3
  1927. * nbr_base = 10
  1928. *
  1929. * pstr = "???" See Note #6b
  1930. *
  1931. * (c) If the number to format ('nbr') is negative but the number of digits to format
  1932. * ('nbr_dig') is equal to the number of significant integer digits of the number
  1933. * to format ('nbr'); then an invalid string is formatted instead of truncating
  1934. * the negative sign.
  1935. *
  1936. * Example :
  1937. *
  1938. * nbr = -23456
  1939. * nbr_dig = 5
  1940. * nbr_base = 10
  1941. *
  1942. * pstr = "?????" See Note #6b
  1943. *
  1944. * (2) The number's base MUST be between 2 & 36, inclusive.
  1945. *
  1946. * (3) Leading character option prepends leading characters prior to the first non-zero digit.
  1947. *
  1948. * (a) (1) Leading character MUST be a printable ASCII character.
  1949. *
  1950. * (2) (A) Leading character MUST NOT be a number base digit, ...
  1951. * (B) with the exception of '0'.
  1952. *
  1953. * (b) (1) The number of leading characters is such that the total number of significant
  1954. * integer digits plus the number of leading characters plus possible negative
  1955. * sign character is equal to the requested number of integer digits to format
  1956. * ('nbr_dig').
  1957. *
  1958. * Examples :
  1959. *
  1960. * nbr = 23456
  1961. * nbr_dig = 7
  1962. * nbr_base = 10
  1963. * lead_char = ' '
  1964. *
  1965. * pstr = " 23456"
  1966. *
  1967. *
  1968. * nbr = -23456
  1969. * nbr_dig = 7
  1970. * nbr_base = 10
  1971. * lead_char = ' '
  1972. *
  1973. * pstr = " -23456"
  1974. *
  1975. * (2) (A) If the number to format ('nbr') is negative AND the leading character
  1976. * ('lead_char') is a '0' digit; then the negative sign character
  1977. * prefixes all leading characters prior to the formatted number.
  1978. *
  1979. * Examples :
  1980. *
  1981. * nbr = -23456
  1982. * nbr_dig = 8
  1983. * nbr_base = 10
  1984. * lead_char = '0'
  1985. *
  1986. * pstr = "-0023456"
  1987. *
  1988. *
  1989. * nbr = -43981
  1990. * nbr_dig = 8
  1991. * nbr_base = 16
  1992. * lead_char = '0'
  1993. * lower_case = DEF_NO
  1994. *
  1995. * pstr = "-000ABCD"
  1996. *
  1997. * (B) If the number to format ('nbr') is negative AND the leading character
  1998. * ('lead_char') is NOT a '0' digit; then the negative sign character
  1999. * immediately prefixes the most significant digit of the formatted number.
  2000. *
  2001. * Examples :
  2002. *
  2003. * nbr = -23456
  2004. * nbr_dig = 8
  2005. * nbr_base = 10
  2006. * lead_char = '#'
  2007. *
  2008. * pstr = "##-23456"
  2009. *
  2010. *
  2011. * nbr = -43981
  2012. * nbr_dig = 8
  2013. * nbr_base = 16
  2014. * lead_char = '#'
  2015. * lower_case = DEF_YES
  2016. *
  2017. * pstr = "###-abcd"
  2018. *
  2019. * (c) (1) If the value of the number to format is zero ...
  2020. * (2) ... & the number of digits to format is non-zero, ...
  2021. * (3) ... but NO leading character available; ...
  2022. * (4) ... then one digit of '0' value is formatted.
  2023. *
  2024. * This is NOT a leading character; but a single integer digit of '0' value.
  2025. *
  2026. * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
  2027. * array formatting.
  2028. *
  2029. * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
  2030. * terminate option DISABLED will cause character string run-on.
  2031. *
  2032. * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
  2033. *
  2034. * (b) To prevent character buffer overrun :
  2035. *
  2036. * Character array size MUST be >= ('nbr_dig' +
  2037. * 1 negative sign +
  2038. * 1 'NUL' terminator) characters
  2039. *
  2040. * (6) For any unsuccessful string format or error(s), an invalid string of question marks
  2041. * ('?') will be formatted, where the number of question marks is determined by the
  2042. * number of digits to format ('nbr_dig') :
  2043. *
  2044. * Invalid string's { (a) 0 (NULL string) , if 'nbr_dig' = 0
  2045. * number of = {
  2046. * question marks { (b) 'nbr_dig' , if 'nbr_dig' > 0
  2047. *
  2048. *********************************************************************************************************
  2049. */
  2050. CPU_CHAR *Str_FmtNbr_Int32S (CPU_INT32S nbr,
  2051. CPU_INT08U nbr_dig,
  2052. CPU_INT08U nbr_base,
  2053. CPU_CHAR lead_char,
  2054. CPU_BOOLEAN lower_case,
  2055. CPU_BOOLEAN nul,
  2056. CPU_CHAR *pstr)
  2057. {
  2058. CPU_CHAR *pstr_fmt;
  2059. CPU_INT32S nbr_fmt;
  2060. CPU_BOOLEAN nbr_neg;
  2061. if (nbr < 0) { /* If nbr neg, ... */
  2062. nbr_fmt = -nbr; /* ... negate nbr. */
  2063. nbr_neg = DEF_YES;
  2064. } else {
  2065. nbr_fmt = nbr;
  2066. nbr_neg = DEF_NO;
  2067. }
  2068. pstr_fmt = Str_FmtNbr_Int32((CPU_INT32U)nbr_fmt, /* Fmt signed int into str. */
  2069. nbr_dig,
  2070. nbr_base,
  2071. nbr_neg,
  2072. lead_char,
  2073. lower_case,
  2074. nul,
  2075. pstr);
  2076. return (pstr_fmt);
  2077. }
  2078. /*
  2079. *********************************************************************************************************
  2080. * Str_FmtNbr_32()
  2081. *
  2082. * Description : Format number into a multi-digit character string.
  2083. *
  2084. * Argument(s) : nbr Number to format (see Note #1).
  2085. *
  2086. * nbr_dig Number of decimal digits to format (see Note #2).
  2087. *
  2088. * nbr_dp Number of decimal point digits to format.
  2089. *
  2090. * lead_char Prepend leading character (see Note #3) :
  2091. *
  2092. * '\0' Do NOT prepend leading character to string.
  2093. * Printable character Prepend leading character to string.
  2094. * Unprintable character Format invalid string (see Note #6d).
  2095. *
  2096. * nul Append terminating NULL-character (see Note #4) :
  2097. *
  2098. * DEF_NO Do NOT append terminating NULL-character to string.
  2099. * DEF_YES Append terminating NULL-character to string.
  2100. *
  2101. * pstr Pointer to character array to return formatted number string (see Note #5).
  2102. *
  2103. * Return(s) : Pointer to formatted string, if NO error(s) [see Note #6c].
  2104. *
  2105. * Pointer to NULL, otherwise.
  2106. *
  2107. * Caller(s) : Application.
  2108. *
  2109. * Note(s) : (1) (a) The maximum accuracy for 32-bit floating-point numbers :
  2110. *
  2111. *
  2112. * Maximum Accuracy log [Internal-Base ^ (Number-Internal-Base-Digits)]
  2113. * 32-bit Floating-point Number = -----------------------------------------------------
  2114. * log [External-Base]
  2115. *
  2116. * log [2 ^ 24]
  2117. * = --------------
  2118. * log [10]
  2119. *
  2120. * < 7.225 Base-10 Digits
  2121. *
  2122. * where
  2123. * Internal-Base Internal number base of floating-
  2124. * point numbers (i.e. 2)
  2125. * External-Base External number base of floating-
  2126. * point numbers (i.e. 10)
  2127. * Number-Internal-Base-Digits Number of internal number base
  2128. * significant digits (i.e. 24)
  2129. *
  2130. * (b) Some CPUs' &/or compilers' floating-point implementations MAY further reduce the
  2131. * maximum accuracy.
  2132. *
  2133. * (2) (a) If the total number of digits to format ('nbr_dig + nbr_dp') is zero; then NO
  2134. * formatting is performed except possible NULL-termination of the string (see Note #4).
  2135. *
  2136. * Example :
  2137. *
  2138. * nbr = -23456.789
  2139. * nbr_dig = 0
  2140. * nbr_dp = 0
  2141. *
  2142. * pstr = "" See Note #7a
  2143. *
  2144. * (b) (1) If the number of digits to format ('nbr_dig') is less than the number of
  2145. * significant integer digits of the number to format ('nbr'); then an invalid
  2146. * string is formatted instead of truncating any significant integer digits.
  2147. *
  2148. * Example :
  2149. *
  2150. * nbr = 23456.789
  2151. * nbr_dig = 3
  2152. * nbr_dp = 2
  2153. *
  2154. * pstr = "??????" See Note #7d
  2155. *
  2156. * (2) If the number to format ('nbr') is negative but the number of digits to format
  2157. * ('nbr_dig') is equal to the number of significant integer digits of the number
  2158. * to format ('nbr'); then an invalid string is formatted instead of truncating
  2159. * the negative sign.
  2160. *
  2161. * Example :
  2162. *
  2163. * nbr = -23456.789
  2164. * nbr_dig = 5
  2165. * nbr_dp = 2
  2166. *
  2167. * pstr = "????????" See Note #7d
  2168. *
  2169. * (3) If the number to format ('nbr') is negative but the number of significant
  2170. * integer digits is zero, & the number of digits to format ('nbr_dig') is one
  2171. * but the number of decimal point digits to format ('nbr_dp') is zero; then
  2172. * an invalid string is formatted instead of truncating the negative sign.
  2173. *
  2174. * Example :
  2175. *
  2176. * nbr = -0.7895
  2177. * nbr_dig = 1
  2178. * nbr_dp = 0
  2179. *
  2180. * pstr = "?" See Note #7d
  2181. *
  2182. * (4) (A) If the number to format ('nbr') is negative but the number of significant
  2183. * integer digits is zero, & the number of digits to format ('nbr_dig') is
  2184. * zero but the number of decimal point digits to format ('nbr_dp') is non-
  2185. * zero; then the negative sign immediately prefixes the decimal point --
  2186. * with NO decimal digits formatted, NOT even a single decimal digit of '0'.
  2187. *
  2188. * Example :
  2189. *
  2190. * nbr = -0.7895
  2191. * nbr_dig = 0
  2192. * nbr_dp = 2
  2193. *
  2194. * pstr = "-.78"
  2195. *
  2196. * (B) If the number to format ('nbr') is positive but the number of significant
  2197. * integer digits is zero, & the number of digits to format ('nbr_dig') is
  2198. * zero but the number of decimal point digits to format ('nbr_dp') is non-
  2199. * zero; then a single decimal digit of '0' prefixes the decimal point.
  2200. *
  2201. * This '0' digit is used whenever a negative sign is not formatted (see
  2202. * Note #2b4A) so that the formatted string's decimal point is not floating,
  2203. * but fixed in the string as the 2nd character.
  2204. *
  2205. * Example :
  2206. *
  2207. * nbr = 0.7895
  2208. * nbr_dig = 0
  2209. * nbr_dp = 2
  2210. *
  2211. * pstr = "0.78"
  2212. *
  2213. * (c) (1) If the total number of digits to format ('nbr_dig + nbr_dp') is greater than ... :
  2214. *
  2215. * (A) ... the maximum accuracy of the CPU's &/or compiler's 32-bit floating-point
  2216. * numbers, digits following all significantly-accurate digits of the number to
  2217. * format ('nbr') will be inaccurate; ...
  2218. * (B) ... the configured maximum accuracy ('LIB_STR_CFG_FP_MAX_NBR_DIG_SIG'), all
  2219. * digits or decimal places following all significantly-accurate digits of the
  2220. * number to format ('nbr') will be replaced & formatted with zeros ('0').
  2221. *
  2222. * Example :
  2223. *
  2224. * nbr = 123456789.012345
  2225. * nbr_dig = 9
  2226. * nbr_dp = 6
  2227. * LIB_STR_CFG_FP_MAX_NBR_DIG_SIG = 7
  2228. *
  2229. * pstr = "123456700.000000"
  2230. *
  2231. * (2) Therefore, one or more least-significant digit(s) of the number to format ('nbr')
  2232. * MAY be rounded & not necessarily truncated due to the inaccuracy of the CPU's
  2233. * &/or compiler's floating-point implementation.
  2234. *
  2235. * See also Note #1.
  2236. *
  2237. * (3) Leading character option prepends leading characters prior to the first non-zero digit.
  2238. *
  2239. * (a) (1) Leading character MUST be a printable ASCII character.
  2240. *
  2241. * (2) (A) Leading character MUST NOT be a base-10 digit, ...
  2242. * (B) with the exception of '0'.
  2243. *
  2244. * (b) (1) The number of leading characters is such that the total number of significant
  2245. * integer digits plus the number of leading characters plus possible negative
  2246. * sign character is equal to the requested number of integer digits to format
  2247. * ('nbr_dig').
  2248. *
  2249. * Examples :
  2250. *
  2251. * nbr = 23456.789
  2252. * nbr_dig = 7
  2253. * nbr_dp = 2
  2254. * lead_char = ' '
  2255. *
  2256. * pstr = " 23456.78"
  2257. *
  2258. *
  2259. * nbr = -23456.789
  2260. * nbr_dig = 7
  2261. * nbr_dp = 2
  2262. * lead_char = ' '
  2263. *
  2264. * pstr = " -23456.78"
  2265. *
  2266. * (2) (A) If the number to format ('nbr') is negative AND the leading character
  2267. * ('lead_char') is a '0' digit; then the negative sign character
  2268. * prefixes all leading characters prior to the formatted number.
  2269. *
  2270. * Example :
  2271. *
  2272. * nbr = -23456.789
  2273. * nbr_dig = 8
  2274. * nbr_dp = 2
  2275. * lead_char = '0'
  2276. *
  2277. * pstr = "-0023456.78"
  2278. *
  2279. * (B) If the number to format ('nbr') is negative AND the leading character
  2280. * ('lead_char') is NOT a '0' digit; then the negative sign character
  2281. * immediately prefixes the most significant digit of the formatted number.
  2282. *
  2283. * Examples :
  2284. *
  2285. * nbr = -23456.789
  2286. * nbr_dig = 8
  2287. * nbr_dp = 2
  2288. * lead_char = '#'
  2289. *
  2290. * pstr = "##-23456.78"
  2291. *
  2292. * (c) (1) If the integer value of the number to format is zero & ...
  2293. * (2) ... the number of digits to format is greater than one ...
  2294. * (3) ... OR the number is NOT negative, ...
  2295. * (4) ... but NO leading character available; ...
  2296. * (5) ... then one digit of '0' value is formatted.
  2297. *
  2298. * This is NOT a leading character; but a single integer digit of '0' value.
  2299. *
  2300. * See also Note #2b4B.
  2301. *
  2302. * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
  2303. * array formatting.
  2304. *
  2305. * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
  2306. * terminate option DISABLED will cause character string run-on.
  2307. *
  2308. * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
  2309. *
  2310. * (b) To prevent character buffer overrun :
  2311. *
  2312. * Character array size MUST be >= ('nbr_dig' +
  2313. * 'nbr_dp' +
  2314. * 1 negative sign +
  2315. * 1 decimal point +
  2316. * 1 'NUL' terminator) characters
  2317. *
  2318. * (6) String format terminates when :
  2319. *
  2320. * (a) Format string pointer is passed a NULL pointer.
  2321. * (1) No string formatted; NULL pointer returned.
  2322. *
  2323. * (b) Total number of digits to format ('nbr_dig + nbr_dp') is zero.
  2324. * (1) NULL string formatted (see Note #7a); NULL pointer returned.
  2325. *
  2326. * (c) Number of digits to format ('nbr_dig') is less than number of significant
  2327. * integer digits of the number to format ('nbr'), including possible
  2328. * negative sign.
  2329. * (1) Invalid string formatted (see Note #7); NULL pointer returned.
  2330. *
  2331. * (d) Lead character is NOT a valid, printable character (see Note #3a).
  2332. * (1) Invalid string formatted (see Note #7); NULL pointer returned.
  2333. *
  2334. * (e) Number successfully formatted into character string array.
  2335. *
  2336. * (7) For any unsuccessful string format or error(s), an invalid string of question marks
  2337. * ('?') will be formatted, where the number of question marks is determined by the
  2338. * number of digits ('nbr_dig') & number of decimal point digits ('nbr_dp') to format :
  2339. *
  2340. * { (a) 0 (NULL string) , if 'nbr_dig' = 0 AND
  2341. * { 'nbr_dp' = 0
  2342. * {
  2343. * { (b) 'nbr_dig' , if 'nbr_dig' > 0 AND
  2344. * { 'nbr_dp' = 0
  2345. * Invalid string's {
  2346. * number of = { (c) ['nbr_dp' + , if 'nbr_dig' = 0 AND
  2347. * question marks { 1 (for decimal point) + 'nbr_dp' > 0
  2348. * { 1 (for negative sign) ]
  2349. * {
  2350. * { (d) ['nbr_dig' + , if 'nbr_dig' > 0 AND
  2351. * { 'nbr_dp' + 'nbr_dp' > 0
  2352. * { 1 (for decimal point) ]
  2353. *
  2354. *********************************************************************************************************
  2355. */
  2356. #if (LIB_STR_CFG_FP_EN == DEF_ENABLED)
  2357. CPU_CHAR *Str_FmtNbr_32 (CPU_FP32 nbr,
  2358. CPU_INT08U nbr_dig,
  2359. CPU_INT08U nbr_dp,
  2360. CPU_CHAR lead_char,
  2361. CPU_BOOLEAN nul,
  2362. CPU_CHAR *pstr)
  2363. {
  2364. CPU_CHAR *pstr_fmt;
  2365. CPU_DATA i;
  2366. CPU_FP32 nbr_fmt;
  2367. CPU_FP32 nbr_log;
  2368. CPU_INT32U nbr_shiftd;
  2369. CPU_INT16U nbr_dig_max;
  2370. CPU_INT16U nbr_dig_sig = 0;
  2371. CPU_INT08U nbr_neg_sign;
  2372. CPU_INT08U dig_val;
  2373. CPU_FP32 dig_exp;
  2374. CPU_FP32 dp_exp;
  2375. CPU_BOOLEAN lead_char_dig;
  2376. CPU_BOOLEAN lead_char_fmtd = DEF_NO;
  2377. CPU_BOOLEAN lead_char_0;
  2378. CPU_BOOLEAN fmt_invalid;
  2379. CPU_BOOLEAN print_char;
  2380. CPU_BOOLEAN nbr_neg;
  2381. CPU_BOOLEAN nbr_neg_fmtd = DEF_NO;
  2382. /* ---------------- VALIDATE FMT ARGS ----------------- */
  2383. if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if str ptr NULL (see Note #6a). */
  2384. return ((CPU_CHAR *)0);
  2385. }
  2386. dig_exp = 1.0f;
  2387. fmt_invalid = DEF_NO;
  2388. lead_char_0 = (lead_char == '0') ? DEF_YES : DEF_NO; /* Chk if lead char a '0' dig (see Note #3b2). */
  2389. nbr_fmt = 0.0f;
  2390. nbr_neg = DEF_NO;
  2391. if ((nbr_dig < 1) && (nbr_dp < 1)) { /* If nbr digs/dps = 0, ... */
  2392. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6b). */
  2393. }
  2394. if (lead_char != (CPU_CHAR)'\0') {
  2395. print_char = ASCII_IsPrint(lead_char);
  2396. if (print_char != DEF_YES) { /* If lead char non-printable (see Note #3a1), ... */
  2397. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6d). */
  2398. } else if (lead_char != '0') { /* Chk lead char for non-0 dig. */
  2399. lead_char_dig = ASCII_IsDig(lead_char);
  2400. if (lead_char_dig == DEF_YES) { /* If lead char non-0 dig (see Note #3a2A), ... */
  2401. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6d). */
  2402. }
  2403. }
  2404. }
  2405. /* ----------------- PREPARE NBR FMT ------------------ */
  2406. pstr_fmt = pstr;
  2407. if (fmt_invalid == DEF_NO) {
  2408. if (nbr < 0.0f) { /* If nbr neg, ... */
  2409. nbr_fmt = -nbr; /* ... negate nbr. */
  2410. nbr_neg_sign = 1u;
  2411. nbr_neg = DEF_YES;
  2412. } else {
  2413. nbr_fmt = nbr;
  2414. nbr_neg_sign = 0u;
  2415. nbr_neg = DEF_NO;
  2416. }
  2417. nbr_log = nbr_fmt;
  2418. nbr_dig_max = 0u;
  2419. while (nbr_log >= 1.0f) { /* While base-10 digs avail, ... */
  2420. nbr_dig_max++; /* ... calc max nbr digs. */
  2421. nbr_log /= 10.0f;
  2422. }
  2423. if (((nbr_dig >= (nbr_dig_max + nbr_neg_sign)) || /* If req'd nbr digs >= (max nbr digs + neg sign) .. */
  2424. (nbr_dig_max < 1)) && /* .. or NO nbr digs, .. */
  2425. ((nbr_dig > 1) || /* .. but NOT [(req'd nbr dig = 1) AND .. */
  2426. (nbr_dp > 0) || /* .. (req'd nbr dp = 0) AND .. */
  2427. (nbr_neg == DEF_NO))) { /* .. ( nbr neg )] (see Note #2b3). */
  2428. /* .. prepare nbr digs to fmt. */
  2429. for (i = 1u; i < nbr_dig; i++) {
  2430. dig_exp *= 10.0f;
  2431. }
  2432. nbr_neg_fmtd = DEF_NO;
  2433. nbr_dig_sig = 0u;
  2434. lead_char_fmtd = DEF_NO;
  2435. } else { /* Else if nbr trunc'd, ... */
  2436. fmt_invalid = DEF_YES; /* ... fmt invalid str (see Note #6c). */
  2437. }
  2438. }
  2439. /* ------------------- FMT NBR STR -------------------- */
  2440. for (i = nbr_dig; i > 0; i--) { /* Fmt str for desired nbr digs : */
  2441. if (fmt_invalid == DEF_NO) {
  2442. if (nbr_dig_sig < LIB_STR_CFG_FP_MAX_NBR_DIG_SIG) { /* If nbr sig digs < max, fmt str digs; ... */
  2443. nbr_shiftd = (CPU_INT32U)(nbr_fmt / dig_exp);
  2444. if ((nbr_shiftd > 0) || /* If shifted nbr > 0 ... */
  2445. (i == 1u)) { /* ... OR on one's dig to fmt (see Note #3c1), ... */
  2446. /* ... calc & fmt dig val; ... */
  2447. if ((nbr_neg == DEF_YES) && /* If nbr neg ... */
  2448. (nbr_neg_fmtd == DEF_NO )) { /* ... but neg sign NOT yet fmt'd; ... */
  2449. if (lead_char_fmtd == DEF_YES) { /* ... & if lead char(s) fmt'd, ... */
  2450. pstr_fmt--; /* ... replace last lead char w/ ... */
  2451. }
  2452. *pstr_fmt++ = '-'; /* ... prepend neg sign (see Notes #2b & #3b). */
  2453. nbr_neg_fmtd = DEF_YES;
  2454. }
  2455. if (nbr_shiftd > 0) { /* If shifted nbr > 0, ... */
  2456. dig_val = (CPU_INT08U)(nbr_shiftd % 10u);
  2457. *pstr_fmt++ = (CPU_CHAR )(dig_val + '0');
  2458. nbr_dig_sig++; /* ... inc nbr sig digs; ... */
  2459. } else if ((nbr_dig > 1) || /* ... else if req'd digs > 1 ... */
  2460. (nbr_neg == DEF_NO)) { /* ... or non-neg nbr, ... */
  2461. *pstr_fmt++ = '0'; /* ... fmt one '0' char (see Note #3c5). */
  2462. }
  2463. } else if ((nbr_neg == DEF_YES) && /* ... else if nbr neg ... */
  2464. (lead_char_0 == DEF_YES) && /* ... & lead char a '0' dig ... */
  2465. (nbr_neg_fmtd == DEF_NO )) { /* ... but neg sign NOT yet fmt'd, ... */
  2466. *pstr_fmt++ = '-'; /* ... prepend neg sign (see Note #3b); ... */
  2467. nbr_neg_fmtd = DEF_YES;
  2468. } else if (lead_char != (CPU_CHAR)'\0') { /* ... else if avail, ... */
  2469. *pstr_fmt++ = lead_char; /* ... fmt lead char. */
  2470. lead_char_fmtd = DEF_YES;
  2471. }
  2472. dig_exp /= 10.0f; /* Shift to next least-sig dig. */
  2473. } else { /* ... else append non-sig 0's (see Note #2c2). */
  2474. *pstr_fmt++ = '0';
  2475. }
  2476. } else { /* Else fmt '?' for invalid str (see Note #7). */
  2477. *pstr_fmt++ = '?';
  2478. }
  2479. }
  2480. if (nbr_dp > 0) { /* Fmt str for desired nbr dp : */
  2481. if (nbr_dig < 1) { /* If NO digs fmt'd; ... */
  2482. if (fmt_invalid == DEF_NO) { /* ... nbr fmt valid, ... */
  2483. if ((nbr_neg == DEF_YES) && /* ... nbr neg ... */
  2484. (nbr_neg_fmtd == DEF_NO )) { /* ... but neg sign NOT yet fmt'd, ... */
  2485. *pstr_fmt++ = '-'; /* ... prepend neg sign (see Notes #2b & #3b); ... */
  2486. } else { /* ... else prepend 1 dig of '0' (see Note #3c5) ... */
  2487. *pstr_fmt++ = '0';
  2488. }
  2489. } else { /* ... else fmt '?' for invalid str (see Note #7). */
  2490. *pstr_fmt++ = '?';
  2491. }
  2492. }
  2493. if (fmt_invalid == DEF_NO) { /* If nbr fmt valid, ... */
  2494. *pstr_fmt++ = '.'; /* ... append dp prior to dp conversion. */
  2495. } else { /* Else fmt '?' for invalid str (see Note #7). */
  2496. *pstr_fmt++ = '?';
  2497. }
  2498. dp_exp = 10.0f;
  2499. for (i = 0u; i < nbr_dp; i++) {
  2500. if (fmt_invalid == DEF_NO) {
  2501. /* If nbr sig digs < max, fmt str dps; ... */
  2502. if (nbr_dig_sig < LIB_STR_CFG_FP_MAX_NBR_DIG_SIG) {
  2503. nbr_shiftd = (CPU_INT32U)(nbr_fmt * dp_exp);
  2504. dig_val = (CPU_INT08U)(nbr_shiftd % 10u);
  2505. *pstr_fmt++ = (CPU_CHAR )(dig_val + '0');
  2506. dp_exp *= 10.0f; /* Shift to next least-sig dp. */
  2507. if ((nbr_shiftd > 0) || /* If shifted nbr > 0 ... */
  2508. (nbr_dig_sig > 0)) { /* ... OR > 0 sig digs already fmt'd, ... */
  2509. nbr_dig_sig++; /* ... inc nbr sig digs. */
  2510. }
  2511. } else { /* ... else append non-sig 0's (see Note #2c2). */
  2512. *pstr_fmt++ = '0';
  2513. }
  2514. } else { /* Else fmt '?' for invalid str (see Note #7). */
  2515. *pstr_fmt++ = '?';
  2516. }
  2517. }
  2518. }
  2519. if (nul != DEF_NO) { /* If NOT DISABLED, append NULL char (see Note #4). */
  2520. *pstr_fmt = (CPU_CHAR)'\0';
  2521. }
  2522. if (fmt_invalid != DEF_NO) { /* Rtn NULL for invalid str fmt (see Notes #6a - #6d). */
  2523. return ((CPU_CHAR *)0);
  2524. }
  2525. return (pstr); /* Rtn ptr to fmt'd str (see Note #6e). */
  2526. }
  2527. #endif
  2528. /*
  2529. *********************************************************************************************************
  2530. * Str_ParseNbr_Int32U()
  2531. *
  2532. * Description : Parse 32-bit unsigned integer from string.
  2533. *
  2534. * Argument(s) : pstr Pointer to string (see Notes #1 & #2a).
  2535. *
  2536. * pstr_next Optional pointer to a variable to ... :
  2537. *
  2538. * (a) Return a pointer to first character following the integer string,
  2539. * if NO error(s) [see Note #2a2B2];
  2540. * (b) Return a pointer to 'pstr',
  2541. * otherwise (see Note #2a2A2).
  2542. *
  2543. * nbr_base Base of number to parse (see Notes #2a1B1 & #2a2B1).
  2544. *
  2545. * Return(s) : Parsed integer, if integer parsed with NO overflow (see Note #2a3A).
  2546. *
  2547. * DEF_INT_32U_MAX_VAL, if integer parsed but overflowed (see Note #2a3A1).
  2548. *
  2549. * 0, otherwise (see Note #2a3B).
  2550. *
  2551. * Caller(s) : Application.
  2552. *
  2553. * Note(s) : (1) String buffer NOT modified.
  2554. *
  2555. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : DESCRIPTION' states that "these
  2556. * functions shall convert the initial portion of the string pointed to by 'str' ('pstr')
  2557. * to a type unsigned long ... representation" :
  2558. *
  2559. * (1) "First, they decompose the input string into three parts" :
  2560. *
  2561. * (A) "An initial, possibly empty, sequence of white-space characters [as specified
  2562. * by isspace()]."
  2563. *
  2564. * (1) "The subject sequence is defined as the longest initial subsequence of the
  2565. * input string, starting with the first non-white-space character that is of
  2566. * the expected form. The subject sequence shall contain no characters if the
  2567. * input string is empty or consists entirely of white-space characters."
  2568. *
  2569. * (B) (1) "A subject sequence interpreted as an integer represented in some radix
  2570. * determined by the value of 'base' ('nbr_base')" :
  2571. *
  2572. * (a) "If the value of 'base' ('nbr_base') is 0, the expected form of the
  2573. * subject sequence is that of a decimal constant, octal constant, or
  2574. * hexadecimal constant" :
  2575. *
  2576. * (1) "A decimal constant begins with a non-zero digit, and consists of a
  2577. * sequence of decimal digits."
  2578. *
  2579. * (2) "An octal constant consists of the prefix '0' optionally followed by
  2580. * a sequence of the digits '0' to '7' only."
  2581. *
  2582. * (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
  2583. * by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
  2584. * (or 'F') with values 10 to 15 respectively."
  2585. *
  2586. * (b) "If the value of 'base' ('nbr_base') is between 2 and 36, the expected form
  2587. * of the subject sequence is a sequence of letters and digits representing
  2588. * an integer with the radix specified by 'base' ('nbr_base')" :
  2589. *
  2590. * (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
  2591. * ascribed the values 10 to 35"; ...
  2592. * (B) "only letters whose ascribed values are less than that of base
  2593. * are permitted."
  2594. *
  2595. * (2) (A) "If the value of 'base' ('nbr_base') is 16, the characters '0x' or
  2596. * '0X' may optionally precede the sequence of letters and digits."
  2597. *
  2598. * (B) Although NO specification states that "if the value of 'base'
  2599. * ('nbr_base') is" 8, the '0' character "may optionally precede
  2600. * the sequence of letters and digits"; it seems reasonable to
  2601. * allow the '0' character to be optionally parsed.
  2602. *
  2603. * (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
  2604. *
  2605. * (a) However, it does NOT seem reasonable to parse & convert a negative number
  2606. * integer string into an unsigned integer.
  2607. *
  2608. * (C) (1) (a) "A final string of one or more unrecognized characters," ...
  2609. * (b) "including the terminating null byte of the input string" ...
  2610. * (2) "other than a sign or a permissible letter or digit."
  2611. *
  2612. * (2) Second, "they shall attempt to convert the subject sequence to an unsigned integer" :
  2613. *
  2614. * (A) "If the subject sequence is empty or does not have the expected form" :
  2615. *
  2616. * (1) "no conversion [is] performed"; ...
  2617. * (2) "the value of 'str' ('pstr') [is] stored in the object pointed to by 'endptr'
  2618. * ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null pointer."
  2619. *
  2620. * (B) "If the subject sequence has the expected form" :
  2621. *
  2622. * (1) (a) "and the value of 'base' ('nbr_base') is 0, the sequence of characters
  2623. * starting with the first digit shall be interpreted as an integer constant."
  2624. *
  2625. * (b) "and the value of 'base' ('nbr_base') is between 2 and 36, it shall be
  2626. * used as the base for conversion, ascribing to each letter its value as
  2627. * given above" (see Note #2a1B1b1A).
  2628. *
  2629. * (2) "A pointer to the final string shall be stored in the object pointed to by
  2630. * 'endptr' ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null
  2631. * pointer."
  2632. *
  2633. * (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : RETURN VALUE' states that :
  2634. *
  2635. * (A) "Upon successful completion, these functions shall return the converted value."
  2636. * (1) "If the correct value is outside the range of representable values, {ULONG_MAX}
  2637. * ... shall be returned."
  2638. *
  2639. * (B) "If no conversion could be performed, 0 shall be returned."
  2640. *
  2641. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  2642. * shall fail if" :
  2643. *
  2644. * (A) "[EINVAL] - The value of 'base' ('nbr_base') is not supported."
  2645. *
  2646. * (B) "[ERANGE] - The value to be returned is not representable."
  2647. *
  2648. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  2649. * may fail if" :
  2650. *
  2651. * (A) "[EINVAL] - No conversion could be performed."
  2652. *
  2653. * (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
  2654. *
  2655. * (a) Valid parse string integer :
  2656. *
  2657. * pstr = " ABCDE xyz"
  2658. * nbr_base = 16
  2659. *
  2660. * nbr = 703710
  2661. * pstr_next = " xyz"
  2662. *
  2663. *
  2664. * (b) Invalid parse string integer :
  2665. *
  2666. * pstr = " ABCDE"
  2667. * nbr_base = 10
  2668. *
  2669. * nbr = 0
  2670. * pstr_next = pstr = " ABCDE"
  2671. *
  2672. *
  2673. * (c) Valid hexadecimal parse string integer :
  2674. *
  2675. * pstr = " 0xGABCDE"
  2676. * nbr_base = 16
  2677. *
  2678. * nbr = 0
  2679. * pstr_next = "xGABCDE"
  2680. *
  2681. *
  2682. * (d) Valid decimal parse string integer ('0x' prefix ignored
  2683. * following invalid hexadecimal characters) :
  2684. *
  2685. * pstr = " 0xGABCDE"
  2686. * nbr_base = 0
  2687. *
  2688. * nbr = 0
  2689. * pstr_next = "xGABCDE"
  2690. *
  2691. *
  2692. * (e) Valid decimal parse string integer ('0' prefix ignored
  2693. * following invalid octal characters) :
  2694. *
  2695. * pstr = " 0GABCDE"
  2696. * nbr_base = 0
  2697. *
  2698. * nbr = 0
  2699. * pstr_next = "GABCDE"
  2700. *
  2701. *
  2702. * (f) Parse string integer overflow :
  2703. *
  2704. * pstr = " 12345678901234567890*123456"
  2705. * nbr_base = 10
  2706. *
  2707. * nbr = DEF_INT_32U_MAX_VAL
  2708. * pstr_next = "*123456"
  2709. *
  2710. *
  2711. * (g) Invalid negative unsigned parse string :
  2712. *
  2713. * pstr = " -12345678901234567890*123456"
  2714. * nbr_base = 10
  2715. *
  2716. * nbr = 0
  2717. * pstr_next = pstr = " -12345678901234567890*123456"
  2718. *
  2719. *********************************************************************************************************
  2720. */
  2721. CPU_INT32U Str_ParseNbr_Int32U (const CPU_CHAR *pstr,
  2722. CPU_CHAR **pstr_next,
  2723. CPU_INT08U nbr_base)
  2724. {
  2725. CPU_INT32U nbr;
  2726. nbr = Str_ParseNbr_Int32( pstr, /* Parse/convert str ... */
  2727. pstr_next,
  2728. nbr_base,
  2729. DEF_NO, /* ... as unsigned int (see Note #2a2). */
  2730. (CPU_BOOLEAN *)0);
  2731. return (nbr);
  2732. }
  2733. /*
  2734. *********************************************************************************************************
  2735. * Str_ParseNbr_Int32S()
  2736. *
  2737. * Description : Parse 32-bit signed integer from string.
  2738. *
  2739. * Argument(s) : pstr Pointer to string (see Notes #1 & #2a).
  2740. *
  2741. * pstr_next Optional pointer to a variable to ... :
  2742. *
  2743. * (a) Return a pointer to first character following the integer string,
  2744. * if NO error(s) [see Note #2a2B2];
  2745. * (b) Return a pointer to 'pstr',
  2746. * otherwise (see Note #2a2A2).
  2747. *
  2748. * nbr_base Base of number to parse (see Notes #2a1B1 & #2a2B1).
  2749. *
  2750. * Return(s) : Parsed integer, if integer parsed with NO over- or underflow (see Note #2a3A).
  2751. *
  2752. * DEF_INT_32S_MIN_VAL, if integer parsed but negatively underflowed (see Note #2a3A1a).
  2753. *
  2754. * DEF_INT_32U_MAX_VAL, if integer parsed but positively overflowed (see Note #2a3A1b).
  2755. *
  2756. * 0, otherwise (see Note #2a3B).
  2757. *
  2758. * Caller(s) : Application.
  2759. *
  2760. * Note(s) : (1) String buffer NOT modified.
  2761. *
  2762. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtol() : DESCRIPTION' states that "these
  2763. * functions shall convert the initial portion of the string pointed to by 'str' ('pstr')
  2764. * to a type long ... representation" :
  2765. *
  2766. * (1) "First, they decompose the input string into three parts" :
  2767. *
  2768. * (A) "An initial, possibly empty, sequence of white-space characters [as specified
  2769. * by isspace()]."
  2770. *
  2771. * (1) "The subject sequence is defined as the longest initial subsequence of the
  2772. * input string, starting with the first non-white-space character that is of
  2773. * the expected form. The subject sequence shall contain no characters if the
  2774. * input string is empty or consists entirely of white-space characters."
  2775. *
  2776. * (B) (1) "A subject sequence interpreted as an integer represented in some radix
  2777. * determined by the value of 'base' ('nbr_base')" :
  2778. *
  2779. * (a) "If the value of 'base' ('nbr_base') is 0, the expected form of the
  2780. * subject sequence is that of a decimal constant, octal constant, or
  2781. * hexadecimal constant" :
  2782. *
  2783. * (1) "A decimal constant begins with a non-zero digit, and consists of a
  2784. * sequence of decimal digits."
  2785. *
  2786. * (2) "An octal constant consists of the prefix '0' optionally followed by
  2787. * a sequence of the digits '0' to '7' only."
  2788. *
  2789. * (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
  2790. * by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
  2791. * (or 'F') with values 10 to 15 respectively."
  2792. *
  2793. * (b) "If the value of 'base' ('nbr_base') is between 2 and 36, the expected form
  2794. * of the subject sequence is a sequence of letters and digits representing
  2795. * an integer with the radix specified by 'base' ('nbr_base')" :
  2796. *
  2797. * (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
  2798. * ascribed the values 10 to 35"; ...
  2799. * (B) "only letters whose ascribed values are less than that of base
  2800. * are permitted."
  2801. *
  2802. * (2) (A) "If the value of 'base' ('nbr_base') is 16, the characters '0x' or
  2803. * '0X' may optionally precede the sequence of letters and digits."
  2804. *
  2805. * (B) Although NO specification states that "if the value of 'base'
  2806. * ('nbr_base') is" 8, the '0' character "may optionally precede
  2807. * the sequence of letters and digits"; it seems reasonable to
  2808. * allow the '0' character to be optionally parsed.
  2809. *
  2810. * (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
  2811. *
  2812. * (a) However, it does NOT seem reasonable to parse & convert a negative number
  2813. * integer string into an unsigned integer.
  2814. *
  2815. * (C) (1) (a) "A final string of one or more unrecognized characters," ...
  2816. * (b) "including the terminating null byte of the input string" ...
  2817. * (2) "other than a sign or a permissible letter or digit."
  2818. *
  2819. * (2) Second, "they shall attempt to convert the subject sequence to an integer" :
  2820. *
  2821. * (A) "If the subject sequence is empty or does not have the expected form" :
  2822. *
  2823. * (1) "no conversion is performed"; ...
  2824. * (2) "the value of 'str' ('pstr') is stored in the object pointed to by 'endptr'
  2825. * ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null pointer."
  2826. *
  2827. * (B) "If the subject sequence has the expected form" :
  2828. *
  2829. * (1) (a) "and the value of 'base' ('nbr_base') is 0, the sequence of characters
  2830. * starting with the first digit shall be interpreted as an integer constant."
  2831. *
  2832. * (b) "and the value of 'base' ('nbr_base') is between 2 and 36, it shall be
  2833. * used as the base for conversion, ascribing to each letter its value as
  2834. * given above" (see Note #2a1B1b1A).
  2835. *
  2836. * (2) "A pointer to the final string shall be stored in the object pointed to by
  2837. * 'endptr' ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null
  2838. * pointer."
  2839. *
  2840. * (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtol() : RETURN VALUE' states that :
  2841. *
  2842. * (A) "Upon successful completion, these functions shall return the converted value."
  2843. *
  2844. * (1) "If the correct value is outside the range of representable values", either
  2845. * of the following "shall be returned" :
  2846. * (a) "{LONG_MIN}" or ...
  2847. * (b) "{LONG_MAX}"
  2848. *
  2849. * (B) "If no conversion could be performed, 0 shall be returned."
  2850. *
  2851. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  2852. * shall fail if" :
  2853. *
  2854. * (A) "[EINVAL] - The value of 'base' ('nbr_base') is not supported."
  2855. *
  2856. * (B) "[ERANGE] - The value to be returned is not representable."
  2857. *
  2858. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  2859. * may fail if" :
  2860. *
  2861. * (A) "[EINVAL] - No conversion could be performed."
  2862. *
  2863. * (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
  2864. *
  2865. * (a) Valid parse string integer :
  2866. *
  2867. * pstr = " ABCDE xyz"
  2868. * nbr_base = 16
  2869. *
  2870. * nbr = 703710
  2871. * pstr_next = " xyz"
  2872. *
  2873. *
  2874. * (b) Invalid parse string integer :
  2875. *
  2876. * pstr = " ABCDE"
  2877. * nbr_base = 10
  2878. *
  2879. * nbr = 0
  2880. * pstr_next = pstr = " ABCDE"
  2881. *
  2882. *
  2883. * (c) Valid hexadecimal parse string integer :
  2884. *
  2885. * pstr = " 0xGABCDE"
  2886. * nbr_base = 16
  2887. *
  2888. * nbr = 0
  2889. * pstr_next = "xGABCDE"
  2890. *
  2891. *
  2892. * (d) Valid decimal parse string integer ('0x' prefix ignored
  2893. * following invalid hexadecimal characters) :
  2894. *
  2895. * pstr = " 0xGABCDE"
  2896. * nbr_base = 0
  2897. *
  2898. * nbr = 0
  2899. * pstr_next = "xGABCDE"
  2900. *
  2901. *
  2902. * (e) Valid decimal parse string integer ('0' prefix ignored
  2903. * following invalid octal characters) :
  2904. *
  2905. * pstr = " 0GABCDE"
  2906. * nbr_base = 0
  2907. *
  2908. * nbr = 0
  2909. * pstr_next = "GABCDE"
  2910. *
  2911. *
  2912. * (f) Parse string integer overflow :
  2913. *
  2914. * pstr = " 12345678901234567890*123456"
  2915. * nbr_base = 10
  2916. *
  2917. * nbr = DEF_INT_32S_MAX_VAL
  2918. * pstr_next = "*123456"
  2919. *
  2920. *
  2921. * (g) Parse string integer underflow :
  2922. *
  2923. * pstr = " -12345678901234567890*123456"
  2924. * nbr_base = 10
  2925. *
  2926. * nbr = DEF_INT_32S_MIN_VAL
  2927. * pstr_next = "*123456"
  2928. *
  2929. *********************************************************************************************************
  2930. */
  2931. CPU_INT32S Str_ParseNbr_Int32S (const CPU_CHAR *pstr,
  2932. CPU_CHAR **pstr_next,
  2933. CPU_INT08U nbr_base)
  2934. {
  2935. CPU_INT32S nbr;
  2936. CPU_INT32U nbr_abs;
  2937. CPU_BOOLEAN nbr_neg;
  2938. nbr_abs = Str_ParseNbr_Int32(pstr, /* Parse/convert str ... */
  2939. pstr_next,
  2940. nbr_base,
  2941. DEF_YES, /* ... as signed int (see Note #2a2). */
  2942. &nbr_neg);
  2943. if (nbr_neg == DEF_NO) { /* Chk for neg nbr & ovf/undf (see Note #2a3A1). */
  2944. nbr = (nbr_abs > (CPU_INT32U) DEF_INT_32S_MAX_VAL) ? (CPU_INT32S)DEF_INT_32S_MAX_VAL
  2945. : (CPU_INT32S)nbr_abs;
  2946. } else {
  2947. nbr = (nbr_abs > (CPU_INT32U)-DEF_INT_32S_MIN_VAL_ONES_CPL) ? (CPU_INT32S)DEF_INT_32S_MIN_VAL
  2948. : -(CPU_INT32S)nbr_abs;
  2949. }
  2950. return (nbr);
  2951. }
  2952. /*
  2953. *********************************************************************************************************
  2954. *********************************************************************************************************
  2955. * LOCAL FUNCTIONS
  2956. *********************************************************************************************************
  2957. *********************************************************************************************************
  2958. */
  2959. /*
  2960. *********************************************************************************************************
  2961. * Str_FmtNbr_Int32()
  2962. *
  2963. * Description : Format 32-bit integer into a multi-digit character string.
  2964. *
  2965. * Argument(s) : nbr Number to format.
  2966. *
  2967. * nbr_dig Number of digits to format (see Note #1).
  2968. *
  2969. * nbr_base Base of number to format (see Note #2).
  2970. *
  2971. * nbr_neg Indicates whether number to format is negative :
  2972. * -------
  2973. * DEF_NO Number is non-negative.
  2974. * DEF_YES Number is negative.
  2975. *
  2976. * Argument validated in Str_FmtNbr_Int32U(),
  2977. * Str_FmtNbr_Int32S().
  2978. *
  2979. * lead_char Prepend leading character (see Note #3) :
  2980. *
  2981. * '\0' Do NOT prepend leading character to string.
  2982. * Printable character Prepend leading character to string.
  2983. * Unprintable character Format invalid string (see Note #6e).
  2984. *
  2985. * lower_case Format alphabetic characters (if any) in lower case :
  2986. *
  2987. * DEF_NO Format alphabetic characters in upper case.
  2988. * DEF_YES Format alphabetic characters in lower case.
  2989. *
  2990. * nul Append terminating NULL-character (see Note #4) :
  2991. *
  2992. * DEF_NO Do NOT append terminating NULL-character to string.
  2993. * DEF_YES Append terminating NULL-character to string.
  2994. *
  2995. * pstr Pointer to character array to return formatted number string (see Note #5).
  2996. *
  2997. * Return(s) : Pointer to formatted string, if NO error(s) [see Note #6f].
  2998. *
  2999. * Pointer to NULL, otherwise.
  3000. *
  3001. * Caller(s) : Str_FmtNbr_Int32U(),
  3002. * Str_FmtNbr_Int32S().
  3003. *
  3004. * Note(s) : (1) (a) The maximum number of digits to format for 32-bit integer numbers :
  3005. *
  3006. *
  3007. * Maximum Number of [ log (Number) ]
  3008. * 32-bit Integer Digits = floor [ -------------- + 1 ]
  3009. * to Format [ log (Base) ]
  3010. *
  3011. * where
  3012. * Number Number to format
  3013. * Base Base of number to format
  3014. *
  3015. * (b) (1) If the number of digits to format ('nbr_dig') is zero; then NO formatting
  3016. * is performed except possible NULL-termination of the string (see Note #4).
  3017. *
  3018. * Example :
  3019. *
  3020. * nbr = -23456
  3021. * nbr_dig = 0
  3022. * nbr_base = 10
  3023. *
  3024. * pstr = "" See Note #7a
  3025. *
  3026. * (2) If the number of digits to format ('nbr_dig') is less than the number of
  3027. * significant integer digits of the number to format ('nbr'); then an invalid
  3028. * string is formatted instead of truncating any significant integer digits.
  3029. *
  3030. * Example :
  3031. *
  3032. * nbr = 23456
  3033. * nbr_dig = 3
  3034. * nbr_base = 10
  3035. *
  3036. * pstr = "???" See Note #7b
  3037. *
  3038. * (3) If the number to format ('nbr') is negative but the number of digits to format
  3039. * ('nbr_dig') is equal to the number of significant integer digits of the number
  3040. * to format ('nbr'); then an invalid string is formatted instead of truncating
  3041. * the negative sign.
  3042. *
  3043. * Example :
  3044. *
  3045. * nbr = -23456
  3046. * nbr_dig = 5
  3047. * nbr_base = 10
  3048. *
  3049. * pstr = "?????" See Note #7b
  3050. *
  3051. * (2) The number's base MUST be between 2 & 36, inclusive.
  3052. *
  3053. * (3) Leading character option prepends leading characters prior to the first non-zero digit.
  3054. *
  3055. * (a) (1) Leading character MUST be a printable ASCII character.
  3056. *
  3057. * (2) (A) Leading character MUST NOT be a number base digit, ...
  3058. * (B) with the exception of '0'.
  3059. *
  3060. * (b) (1) The number of leading characters is such that the total number of significant
  3061. * integer digits plus the number of leading characters plus possible negative
  3062. * sign character is equal to the requested number of integer digits to format
  3063. * ('nbr_dig').
  3064. *
  3065. * Examples :
  3066. *
  3067. * nbr = 23456
  3068. * nbr_dig = 7
  3069. * nbr_base = 10
  3070. * lead_char = ' '
  3071. *
  3072. * pstr = " 23456"
  3073. *
  3074. *
  3075. * nbr = -23456
  3076. * nbr_dig = 7
  3077. * nbr_base = 10
  3078. * lead_char = ' '
  3079. *
  3080. * pstr = " -23456"
  3081. *
  3082. * (2) (A) If the number to format ('nbr') is negative AND the leading character
  3083. * ('lead_char') is a '0' digit; then the negative sign character
  3084. * prefixes all leading characters prior to the formatted number.
  3085. *
  3086. * Examples :
  3087. *
  3088. * nbr = -23456
  3089. * nbr_dig = 8
  3090. * nbr_base = 10
  3091. * lead_char = '0'
  3092. *
  3093. * pstr = "-0023456"
  3094. *
  3095. *
  3096. * nbr = -43981
  3097. * nbr_dig = 8
  3098. * nbr_base = 16
  3099. * lead_char = '0'
  3100. * lower_case = DEF_NO
  3101. *
  3102. * pstr = "-000ABCD"
  3103. *
  3104. * (B) If the number to format ('nbr') is negative AND the leading character
  3105. * ('lead_char') is NOT a '0' digit; then the negative sign character
  3106. * immediately prefixes the most significant digit of the formatted number.
  3107. *
  3108. * Examples :
  3109. *
  3110. * nbr = -23456
  3111. * nbr_dig = 8
  3112. * nbr_base = 10
  3113. * lead_char = '#'
  3114. *
  3115. * pstr = "##-23456"
  3116. *
  3117. *
  3118. * nbr = -43981
  3119. * nbr_dig = 8
  3120. * nbr_base = 16
  3121. * lead_char = '#'
  3122. * lower_case = DEF_YES
  3123. *
  3124. * pstr = "###-abcd"
  3125. *
  3126. * (c) (1) If the value of the number to format is zero ...
  3127. * (2) ... & the number of digits to format is non-zero, ...
  3128. * (3) ... but NO leading character available; ...
  3129. * (4) ... then one digit of '0' value is formatted.
  3130. *
  3131. * This is NOT a leading character; but a single integer digit of '0' value.
  3132. *
  3133. * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
  3134. * array formatting.
  3135. *
  3136. * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
  3137. * terminate option DISABLED will cause character string run-on.
  3138. *
  3139. * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
  3140. *
  3141. * (b) To prevent character buffer overrun :
  3142. *
  3143. * Character array size MUST be >= ('nbr_dig' +
  3144. * 1 negative sign +
  3145. * 1 'NUL' terminator) characters
  3146. *
  3147. * (6) String format terminates when :
  3148. *
  3149. * (a) Format string pointer is passed a NULL pointer.
  3150. * (1) No string formatted; NULL pointer returned.
  3151. *
  3152. * (b) Number of digits to format ('nbr_dig') is zero.
  3153. * (1) NULL string formatted (see Note #7a); NULL pointer returned.
  3154. *
  3155. * (c) Number of digits to format ('nbr_dig') is less than number of significant
  3156. * integer digits of the number to format ('nbr'), including possible
  3157. * negative sign.
  3158. * (1) Invalid string formatted (see Note #7); NULL pointer returned.
  3159. *
  3160. * (d) Base is passed an invalid base (see Note #2).
  3161. * (1) Invalid string format performed; NULL pointer returned.
  3162. *
  3163. * (e) Lead character is NOT a valid, printable character (see Note #3a).
  3164. * (1) Invalid string formatted (see Note #7); NULL pointer returned.
  3165. *
  3166. * (f) Number successfully formatted into character string array.
  3167. *
  3168. * (7) For any unsuccessful string format or error(s), an invalid string of question marks
  3169. * ('?') will be formatted, where the number of question marks is determined by the
  3170. * number of digits to format ('nbr_dig') :
  3171. *
  3172. * Invalid string's { (a) 0 (NULL string) , if 'nbr_dig' = 0
  3173. * number of = {
  3174. * question marks { (b) 'nbr_dig' , if 'nbr_dig' > 0
  3175. *
  3176. *********************************************************************************************************
  3177. */
  3178. static CPU_CHAR *Str_FmtNbr_Int32 (CPU_INT32U nbr,
  3179. CPU_INT08U nbr_dig,
  3180. CPU_INT08U nbr_base,
  3181. CPU_BOOLEAN nbr_neg,
  3182. CPU_CHAR lead_char,
  3183. CPU_BOOLEAN lower_case,
  3184. CPU_BOOLEAN nul,
  3185. CPU_CHAR *pstr)
  3186. {
  3187. CPU_CHAR *pstr_fmt;
  3188. CPU_DATA i;
  3189. CPU_INT32U nbr_fmt = 0;
  3190. CPU_INT32U nbr_log;
  3191. CPU_INT08U nbr_dig_max;
  3192. CPU_INT08U nbr_dig_min;
  3193. CPU_INT08U nbr_dig_fmtd = 0;
  3194. CPU_INT08U nbr_neg_sign;
  3195. CPU_INT08U nbr_lead_char;
  3196. CPU_INT08U dig_val;
  3197. CPU_INT08U lead_char_delta_0;
  3198. CPU_INT08U lead_char_delta_a;
  3199. CPU_BOOLEAN lead_char_dig;
  3200. CPU_BOOLEAN lead_char_0;
  3201. CPU_BOOLEAN fmt_valid = DEF_YES;
  3202. CPU_BOOLEAN print_char;
  3203. CPU_BOOLEAN nbr_neg_fmtd = DEF_NO;
  3204. /* ---------------- VALIDATE FMT ARGS ----------------- */
  3205. if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if str ptr NULL (see Note #6a). */
  3206. return ((CPU_CHAR *)0);
  3207. }
  3208. if (nbr_dig < 1) { /* If nbr digs = 0, ... */
  3209. fmt_valid = DEF_NO; /* ... fmt valid str (see Note #6b). */
  3210. }
  3211. /* If invalid base, ... */
  3212. if ((nbr_base < 2u) ||
  3213. (nbr_base > 36u)) {
  3214. fmt_valid = DEF_NO; /* ... fmt valid str (see Note #6d). */
  3215. }
  3216. if (lead_char != (CPU_CHAR)'\0') {
  3217. print_char = ASCII_IsPrint(lead_char);
  3218. if (print_char != DEF_YES) { /* If lead char non-printable (see Note #3a1), ... */
  3219. fmt_valid = DEF_NO; /* ... fmt valid str (see Note #6e). */
  3220. } else if (lead_char != '0') { /* Chk lead char for non-0 nbr base dig. */
  3221. lead_char_delta_0 = (CPU_INT08U)(lead_char - '0');
  3222. if (lower_case != DEF_YES) {
  3223. lead_char_delta_a = (CPU_INT08U)(lead_char - 'A');
  3224. } else {
  3225. lead_char_delta_a = (CPU_INT08U)(lead_char - 'a');
  3226. }
  3227. lead_char_dig = (((nbr_base <= 10u) && (lead_char_delta_0 < nbr_base)) ||
  3228. ((nbr_base > 10u) && ((lead_char_delta_0 < 10u) ||
  3229. (lead_char_delta_a < (nbr_base - 10u))))) ? DEF_YES : DEF_NO;
  3230. if (lead_char_dig == DEF_YES) { /* If lead char non-0 nbr base dig (see Note #3a2A), ...*/
  3231. fmt_valid = DEF_NO; /* ... fmt valid str (see Note #6e). */
  3232. }
  3233. } else {
  3234. /* Empty Else Statement */
  3235. }
  3236. }
  3237. /* ----------------- PREPARE NBR FMT ------------------ */
  3238. pstr_fmt = pstr;
  3239. lead_char_0 = DEF_NO;
  3240. if (fmt_valid == DEF_YES) {
  3241. nbr_fmt = nbr;
  3242. nbr_log = nbr;
  3243. nbr_dig_max = 1u;
  3244. while (nbr_log >= nbr_base) { /* While nbr base digs avail, ... */
  3245. nbr_dig_max++; /* ... calc max nbr digs. */
  3246. nbr_log /= nbr_base;
  3247. }
  3248. nbr_neg_sign = (nbr_neg == DEF_YES) ? 1u : 0u;
  3249. if (nbr_dig >= (nbr_dig_max + nbr_neg_sign)) { /* If req'd nbr digs >= (max nbr digs + neg sign), ... */
  3250. nbr_neg_fmtd = DEF_NO;
  3251. nbr_dig_min = DEF_MIN(nbr_dig_max, nbr_dig);
  3252. /* ... calc nbr digs to fmt & nbr lead chars. */
  3253. if (lead_char != (CPU_CHAR)'\0') {
  3254. nbr_dig_fmtd = nbr_dig;
  3255. nbr_lead_char = nbr_dig -
  3256. (nbr_dig_min + nbr_neg_sign);
  3257. } else {
  3258. nbr_dig_fmtd = nbr_dig_min + nbr_neg_sign;
  3259. nbr_lead_char = 0u;
  3260. }
  3261. if (nbr_lead_char > 0) { /* If lead chars to fmt, ... */
  3262. lead_char_0 = (lead_char == '0') /* ... chk if lead char a '0' dig (see Note #3a2B). */
  3263. ? DEF_YES : DEF_NO;
  3264. }
  3265. } else { /* Else if nbr trunc'd, ... */
  3266. fmt_valid = DEF_NO; /* ... fmt valid str (see Note #6c). */
  3267. }
  3268. }
  3269. if (fmt_valid == DEF_NO) {
  3270. nbr_dig_fmtd = nbr_dig;
  3271. }
  3272. /* ------------------- FMT NBR STR -------------------- */
  3273. pstr_fmt += nbr_dig_fmtd; /* Start fmt @ least-sig dig. */
  3274. if (nul != DEF_NO) { /* If NOT DISABLED, append NULL char (see Note #4). */
  3275. *pstr_fmt = (CPU_CHAR)'\0';
  3276. }
  3277. pstr_fmt--;
  3278. for (i = 0u; i < nbr_dig_fmtd; i++) { /* Fmt str for desired nbr digs : */
  3279. if (fmt_valid == DEF_YES) {
  3280. if ((nbr_fmt > 0) || /* If fmt nbr > 0 ... */
  3281. (i == 0u)) { /* ... OR on one's dig to fmt (see Note #3c1), ... */
  3282. /* ... calc & fmt dig val; ... */
  3283. dig_val = (CPU_INT08U)(nbr_fmt % nbr_base);
  3284. if (dig_val < 10u) {
  3285. *pstr_fmt-- = (CPU_CHAR)(dig_val + '0');
  3286. } else {
  3287. if (lower_case != DEF_YES) {
  3288. *pstr_fmt-- = (CPU_CHAR)((dig_val - 10u) + 'A');
  3289. } else {
  3290. *pstr_fmt-- = (CPU_CHAR)((dig_val - 10u) + 'a');
  3291. }
  3292. }
  3293. nbr_fmt /= nbr_base; /* Shift to next more-sig dig. */
  3294. } else if ((nbr_neg == DEF_YES) && /* ... else if nbr neg AND ... */
  3295. (((lead_char_0 == DEF_NO ) && /* ... lead char NOT a '0' dig ... */
  3296. (nbr_neg_fmtd == DEF_NO )) || /* ... but neg sign NOT yet fmt'd OR ... */
  3297. ((lead_char_0 != DEF_NO ) && /* ... lead char is a '0' dig ... */
  3298. (i == (nbr_dig_fmtd - 1u))))) { /* ... & on most-sig dig to fmt, ... */
  3299. *pstr_fmt-- = '-'; /* ... prepend neg sign (see Note #3b); ... */
  3300. nbr_neg_fmtd = DEF_YES;
  3301. } else if (lead_char != (CPU_CHAR)'\0') { /* ... else if avail, ... */
  3302. *pstr_fmt-- = lead_char; /* ... fmt lead char. */
  3303. } else {
  3304. /* Empty Else Statement */
  3305. }
  3306. } else { /* Else fmt '?' for invalid str (see Note #7). */
  3307. *pstr_fmt-- = '?';
  3308. }
  3309. }
  3310. if (fmt_valid == DEF_NO) { /* Rtn NULL for invalid str fmt (see Notes #6a - #6e). */
  3311. return ((CPU_CHAR *)0);
  3312. }
  3313. return (pstr); /* Rtn ptr to fmt'd str (see Note #6f). */
  3314. }
  3315. /*
  3316. *********************************************************************************************************
  3317. * Str_ParseNbr_Int32()
  3318. *
  3319. * Description : Parse 32-bit integer from string.
  3320. *
  3321. * Argument(s) : pstr Pointer to string (see Notes #1 & #2a).
  3322. *
  3323. * pstr_next Optional pointer to a variable to ... :
  3324. *
  3325. * (a) Return a pointer to first character following the integer string,
  3326. * if NO error(s) [see Note #2a2B2];
  3327. * (b) Return a pointer to 'pstr',
  3328. * otherwise (see Note #2a2A2).
  3329. *
  3330. * nbr_base Base of number to parse (see Notes #2a1B1 & #2a2B1).
  3331. *
  3332. * nbr_signed Indicates whether number to parse is signed :
  3333. *
  3334. * DEF_NO Number is unsigned.
  3335. * DEF_YES Number is signed.
  3336. *
  3337. * pnbr_neg Pointer to a variable to return if the parsed (signed) number is negative :
  3338. *
  3339. * DEF_NO Number is non-negative.
  3340. * DEF_YES Number is negative.
  3341. *
  3342. * Return(s) : Parsed integer, if integer parsed with NO overflow (see Note #2a3A).
  3343. *
  3344. * DEF_INT_32U_MAX_VAL, if integer parsed but overflowed (see Note #2a3A1).
  3345. *
  3346. * 0, otherwise (see Note #2a3B).
  3347. *
  3348. * Caller(s) : Str_ParseNbr_Int32U(),
  3349. * Str_ParseNbr_Int32S().
  3350. *
  3351. * Note(s) : (1) String buffer NOT modified.
  3352. *
  3353. * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtol() : DESCRIPTION' states that "these
  3354. * functions shall convert the initial portion of the string pointed to by 'str' ('pstr')
  3355. * to a type long ... representation" :
  3356. *
  3357. * (1) "First, they decompose the input string into three parts" :
  3358. *
  3359. * (A) "An initial, possibly empty, sequence of white-space characters [as specified
  3360. * by isspace()]."
  3361. *
  3362. * (1) "The subject sequence is defined as the longest initial subsequence of the
  3363. * input string, starting with the first non-white-space character that is of
  3364. * the expected form. The subject sequence shall contain no characters if the
  3365. * input string is empty or consists entirely of white-space characters."
  3366. *
  3367. * (B) (1) "A subject sequence interpreted as an integer represented in some radix
  3368. * determined by the value of 'base' ('nbr_base')" :
  3369. *
  3370. * (a) "If the value of 'base' ('nbr_base') is 0, the expected form of the
  3371. * subject sequence is that of a decimal constant, octal constant, or
  3372. * hexadecimal constant" :
  3373. *
  3374. * (1) "A decimal constant begins with a non-zero digit, and consists of a
  3375. * sequence of decimal digits."
  3376. *
  3377. * (2) "An octal constant consists of the prefix '0' optionally followed by
  3378. * a sequence of the digits '0' to '7' only."
  3379. *
  3380. * (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
  3381. * by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
  3382. * (or 'F') with values 10 to 15 respectively."
  3383. *
  3384. * (b) "If the value of 'base' ('nbr_base') is between 2 and 36, the expected form
  3385. * of the subject sequence is a sequence of letters and digits representing
  3386. * an integer with the radix specified by 'base' ('nbr_base')" :
  3387. *
  3388. * (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
  3389. * ascribed the values 10 to 35"; ...
  3390. * (B) "only letters whose ascribed values are less than that of base
  3391. * are permitted."
  3392. *
  3393. * (2) (A) "If the value of 'base' ('nbr_base') is 16, the characters '0x' or
  3394. * '0X' may optionally precede the sequence of letters and digits."
  3395. *
  3396. * (B) Although NO specification states that "if the value of 'base'
  3397. * ('nbr_base') is" 8, the '0' character "may optionally precede
  3398. * the sequence of letters and digits"; it seems reasonable to
  3399. * allow the '0' character to be optionally parsed.
  3400. *
  3401. * (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
  3402. *
  3403. * (a) It does NOT seem reasonable to parse & convert a negative number
  3404. * integer string into an unsigned integer. However, a negative sign
  3405. * for an unsigned integer will automatically be parsed as an invalid
  3406. * character (see Note #2aC1).
  3407. *
  3408. * (C) (1) (a) "A final string of one or more unrecognized characters," ...
  3409. * (b) "including the terminating null byte of the input string" ...
  3410. * (2) "other than a sign or a permissible letter or digit."
  3411. *
  3412. * (2) Second, "they shall attempt to convert the subject sequence to an integer" :
  3413. *
  3414. * (A) "If the subject sequence is empty or does not have the expected form" :
  3415. *
  3416. * (1) "no conversion is performed"; ...
  3417. * (2) "the value of 'str' ('pstr') is stored in the object pointed to by 'endptr'
  3418. * ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null pointer."
  3419. *
  3420. * (B) "If the subject sequence has the expected form" :
  3421. *
  3422. * (1) (a) "and the value of 'base' ('nbr_base') is 0, the sequence of characters
  3423. * starting with the first digit shall be interpreted as an integer constant."
  3424. *
  3425. * (b) "and the value of 'base' ('nbr_base') is between 2 and 36, it shall be
  3426. * used as the base for conversion, ascribing to each letter its value as
  3427. * given above" (see Note #2a1B1b1A).
  3428. *
  3429. * (2) "A pointer to the final string shall be stored in the object pointed to by
  3430. * 'endptr' ('pstr_next'), provided that 'endptr' ('pstr_next') is not a null
  3431. * pointer."
  3432. *
  3433. * (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtol() : RETURN VALUE' states that :
  3434. *
  3435. * (A) "Upon successful completion, these functions shall return the converted value."
  3436. * (1) "If the correct value is outside the range of representable values, {LONG_MIN}
  3437. * [or] {LONG_MAX} ... shall be returned."
  3438. *
  3439. * (B) "If no conversion could be performed, 0 shall be returned."
  3440. *
  3441. * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  3442. * shall fail if" :
  3443. *
  3444. * (A) "[EINVAL] - The value of 'base' ('nbr_base') is not supported."
  3445. *
  3446. * (B) "[ERANGE] - The value to be returned is not representable."
  3447. *
  3448. * (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
  3449. * may fail if" :
  3450. *
  3451. * (A) "[EINVAL] - No conversion could be performed."
  3452. *
  3453. * (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
  3454. *
  3455. * (a) Valid parse string integer :
  3456. *
  3457. * pstr = " ABCDE xyz"
  3458. * nbr_base = 16
  3459. *
  3460. * nbr = 703710
  3461. * pstr_next = " xyz"
  3462. *
  3463. *
  3464. * (b) Invalid parse string integer :
  3465. *
  3466. * pstr = " ABCDE"
  3467. * nbr_base = 10
  3468. *
  3469. * nbr = 0
  3470. * pstr_next = pstr = " ABCDE"
  3471. *
  3472. *
  3473. * (c) Valid hexadecimal parse string integer :
  3474. *
  3475. * pstr = " 0xGABCDE"
  3476. * nbr_base = 16
  3477. *
  3478. * nbr = 0
  3479. * pstr_next = "xGABCDE"
  3480. *
  3481. *
  3482. * (d) Valid decimal parse string integer ('0x' prefix ignored
  3483. * following invalid hexadecimal characters) :
  3484. *
  3485. * pstr = " 0xGABCDE"
  3486. * nbr_base = 0
  3487. *
  3488. * nbr = 0
  3489. * pstr_next = "xGABCDE"
  3490. *
  3491. *
  3492. * (e) Valid decimal parse string integer ('0' prefix ignored
  3493. * following invalid octal characters) :
  3494. *
  3495. * pstr = " 0GABCDE"
  3496. * nbr_base = 0
  3497. *
  3498. * nbr = 0
  3499. * pstr_next = "GABCDE"
  3500. *
  3501. *
  3502. * (f) Parse string integer overflow :
  3503. *
  3504. * pstr = " 12345678901234567890*123456"
  3505. * nbr_base = 10
  3506. *
  3507. * nbr = DEF_INT_32U_MAX_VAL
  3508. * pstr_next = "*123456"
  3509. *
  3510. *
  3511. * (g) Parse string integer underflow :
  3512. *
  3513. * pstr = " -12345678901234567890*123456"
  3514. * nbr_base = 10
  3515. *
  3516. * nbr = DEF_INT_32S_MIN_VAL
  3517. * pstr_next = "*123456"
  3518. *
  3519. *
  3520. * (4) String parse terminates when :
  3521. *
  3522. * (a) Base passed an invalid base (see Note #2a1B1b).
  3523. * (1) No conversion performed; 0 returned.
  3524. *
  3525. * (b) (1) Parse string passed a NULL pointer OR empty integer sequence (see Note #2a2A).
  3526. * (A) No conversion performed; 0 returned.
  3527. *
  3528. * (2) Invalid parse string character found (see Note #2a1C).
  3529. * (A) Parsed integer returned.
  3530. * (B) 'pstr_next' points to invalid character.
  3531. *
  3532. * (3) Entire parse string converted (see Note #2a2B).
  3533. * (A) Parsed integer returned.
  3534. * (B) 'pstr_next' points to terminating NULL character.
  3535. *
  3536. * (5) Pointers to variables that return values MUST be initialized PRIOR to all other
  3537. * validation or function handling in case of any error(s).
  3538. *********************************************************************************************************
  3539. */
  3540. static CPU_INT32U Str_ParseNbr_Int32 (const CPU_CHAR *pstr,
  3541. CPU_CHAR **pstr_next,
  3542. CPU_INT08U nbr_base,
  3543. CPU_BOOLEAN nbr_signed,
  3544. CPU_BOOLEAN *pnbr_neg)
  3545. {
  3546. const CPU_CHAR *pstr_parse;
  3547. const CPU_CHAR *pstr_parse_nbr;
  3548. CPU_CHAR *pstr_parse_unused;
  3549. CPU_CHAR parse_char;
  3550. CPU_INT08U parse_dig;
  3551. CPU_INT32U nbr;
  3552. CPU_BOOLEAN nbr_neg_unused;
  3553. CPU_BOOLEAN nbr_dig;
  3554. CPU_BOOLEAN nbr_alpha;
  3555. CPU_BOOLEAN nbr_hex;
  3556. CPU_BOOLEAN nbr_hex_lower;
  3557. CPU_BOOLEAN whitespace;
  3558. CPU_BOOLEAN neg;
  3559. CPU_BOOLEAN ovf;
  3560. CPU_BOOLEAN done;
  3561. /* --------------- VALIDATE PARSE ARGS ---------------- */
  3562. if (pstr_next == (CPU_CHAR **) 0) { /* If NOT avail, ... */
  3563. pstr_next = (CPU_CHAR **)&pstr_parse_unused; /* ... re-cfg NULL rtn ptr to unused local var. */
  3564. (void)pstr_parse_unused; /* Prevent possible 'variable unused' warning. */
  3565. }
  3566. *pstr_next = (CPU_CHAR *)pstr; /* Init rtn str for err (see Note #5). */
  3567. if (pnbr_neg == (CPU_BOOLEAN *) 0) { /* If NOT avail, ... */
  3568. pnbr_neg = (CPU_BOOLEAN *)&nbr_neg_unused; /* ... re-cfg NULL rtn ptr to unused local var. */
  3569. (void)nbr_neg_unused; /* Prevent possible 'variable unused' warning. */
  3570. }
  3571. *pnbr_neg = DEF_NO; /* Init nbr neg for err (see Note #5). */
  3572. if (pstr == (CPU_CHAR *)0) { /* Rtn zero if str ptr NULL (see Note #4b1). */
  3573. return (0u);
  3574. }
  3575. /* Rtn zero if invalid base (see Note #4a). */
  3576. if ((nbr_base == 1u) ||
  3577. (nbr_base > 36u)) {
  3578. return (0u);
  3579. }
  3580. /* ------------- IGNORE PRECEDING CHAR(S) ------------- */
  3581. pstr_parse = pstr; /* Save ptr to init'l str for err (see Note #2a2A2). */
  3582. whitespace = ASCII_IsSpace(*pstr_parse);
  3583. while (whitespace == DEF_YES) { /* Ignore initial white-space char(s) [see Note #2a1A]. */
  3584. pstr_parse++;
  3585. whitespace = ASCII_IsSpace(*pstr_parse);
  3586. }
  3587. switch (*pstr_parse) {
  3588. case '+': /* Ignore pos sign (see Note #2a1B2). */
  3589. pstr_parse++;
  3590. neg = DEF_NO;
  3591. break;
  3592. case '-': /* Validate neg sign (see Note #2a1B2a). */
  3593. if (nbr_signed == DEF_YES) {
  3594. pstr_parse++;
  3595. }
  3596. neg = DEF_YES;
  3597. break;
  3598. default:
  3599. neg = DEF_NO;
  3600. break;
  3601. }
  3602. /* --------- IGNORE NBR BASE PRECEDING CHAR(S) -------- */
  3603. pstr_parse_nbr = pstr_parse; /* Save ptr to str's nbr (see Note #2a1A1). */
  3604. switch (nbr_base) {
  3605. case 0u: /* Determine unspecified nbr base (see Notes #2a1B1a). */
  3606. if (*pstr_parse == '0') { /* If avail, ... */
  3607. pstr_parse++; /* ... adv past '0' prefix (see Note #2a1B1b2). */
  3608. switch (*pstr_parse) {
  3609. case 'x': /* For '0x' prefix, ... */
  3610. case 'X':
  3611. nbr_base = 16u; /* ... set nbr base = 16 (see Note #2a1B1a3). */
  3612. parse_char = (CPU_CHAR)(*(pstr_parse + 1));
  3613. nbr_hex = ASCII_IsDigHex(parse_char);
  3614. if (nbr_hex == DEF_YES) { /* If next char is valid hex dig, ... */
  3615. pstr_parse++; /* ... adv past '0x' prefix (see Note #2a1B1b2A). */
  3616. }
  3617. break;
  3618. default: /* For '0' prefix, ... */
  3619. nbr_base = 8u; /* ... set nbr base = 8 (see Note #2a1B1a2). */
  3620. break;
  3621. }
  3622. } else { /* For non-'0' prefix, ... */
  3623. nbr_base = 10u; /* ... set nbr base = 10 (see Note #2a1B1a1). */
  3624. }
  3625. break;
  3626. case 8u: /* See Note #2a1B1a2. */
  3627. if (*pstr_parse == '0') { /* If avail, ... */
  3628. pstr_parse++; /* ... adv past '0' prefix (see Note #2a1B1b2B). */
  3629. }
  3630. break;
  3631. case 16u: /* See Note #2a1B1a3. */
  3632. if (*pstr_parse == '0') { /* If avail, ... */
  3633. pstr_parse++; /* ... adv past '0' prefix (see Note #2a1B1b2). */
  3634. switch (*pstr_parse) {
  3635. case 'x':
  3636. case 'X':
  3637. parse_char = (CPU_CHAR)(*(pstr_parse + 1));
  3638. nbr_hex = ASCII_IsDigHex(parse_char);
  3639. if (nbr_hex == DEF_YES) { /* If next char is valid hex dig, ... */
  3640. pstr_parse++; /* ... adv past '0x' prefix (see Note #2a1B1b2A). */
  3641. }
  3642. break;
  3643. default:
  3644. break;
  3645. }
  3646. }
  3647. break;
  3648. default: /* See Note #2a1B1b. */
  3649. break;
  3650. }
  3651. /* ------------------ PARSE INT STR ------------------- */
  3652. nbr = 0u;
  3653. ovf = DEF_NO;
  3654. done = DEF_NO;
  3655. while (done == DEF_NO) { /* Parse str for desired nbr base digs (see Note #2a2). */
  3656. parse_char = (CPU_CHAR)*pstr_parse;
  3657. nbr_alpha = ASCII_IsAlphaNum(parse_char);
  3658. if (nbr_alpha == DEF_YES) { /* If valid alpha num nbr dig avail, ... */
  3659. /* ... convert parse char into nbr dig. */
  3660. nbr_dig = ASCII_IsDig(parse_char);
  3661. if (nbr_dig == DEF_YES) {
  3662. parse_dig = (CPU_INT08U)(parse_char - '0');
  3663. } else {
  3664. nbr_hex_lower = ASCII_IsLower(parse_char);
  3665. if (nbr_hex_lower == DEF_YES) {
  3666. parse_dig = ((CPU_INT08U)(parse_char - 'a') + 10u);
  3667. } else {
  3668. parse_dig = ((CPU_INT08U)(parse_char - 'A') + 10u);
  3669. }
  3670. }
  3671. if (parse_dig < nbr_base) { /* If parse char valid for nbr base ... */
  3672. if (ovf == DEF_NO) { /* ... & nbr NOT yet ovf'd, ... */
  3673. if (nbr <= Str_MultOvfThTbl_Int32U[nbr_base]) {
  3674. /* ... merge parse char dig into nbr. */
  3675. nbr *= nbr_base;
  3676. nbr += parse_dig;
  3677. if (nbr < parse_dig) {
  3678. ovf = DEF_YES;
  3679. }
  3680. } else {
  3681. ovf = DEF_YES;
  3682. }
  3683. }
  3684. pstr_parse++;
  3685. } else { /* Invalid char parsed (see Note #2a1C1a). */
  3686. done = DEF_YES;
  3687. }
  3688. } else { /* Invalid OR NULL char parsed (see Note #2a1C1). */
  3689. done = DEF_YES;
  3690. }
  3691. }
  3692. if (ovf == DEF_YES) { /* If nbr ovf'd, ... */
  3693. nbr = DEF_INT_32U_MAX_VAL; /* ... rtn max int val (see Note #2a3A1). */
  3694. }
  3695. if (pstr_parse != pstr_parse_nbr) { /* If final parse str != init'l parse nbr str, .. */
  3696. *pstr_next = (CPU_CHAR *)pstr_parse; /* .. rtn parse str's next char (see Note #2a2B2); .. */
  3697. } else {
  3698. *pstr_next = (CPU_CHAR *)pstr; /* .. else rtn initial parse str (see Note #2a2A2). */
  3699. }
  3700. *pnbr_neg = neg; /* Rtn neg nbr status. */
  3701. return (nbr);
  3702. }