| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

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