UCOS_TI_LM3S_Keil
 全部 结构体 文件 函数 变量 类型定义 宏定义 
lib_str.c
浏览该文件的文档.
1 /*
2 *********************************************************************************************************
3 * uC/LIB
4 * CUSTOM LIBRARY MODULES
5 *
6 * (c) Copyright 2004-2009; Micrium, Inc.; Weston, FL
7 *
8 * All rights reserved. Protected by international copyright laws.
9 *
10 * uC/LIB is provided in source form for FREE evaluation, for educational
11 * use or peaceful research. If you plan on using uC/LIB in a commercial
12 * product you need to contact Micrium to properly license its use in your
13 * product. We provide ALL the source code for your convenience and to
14 * help you experience uC/LIB. The fact that the source code is provided
15 * does NOT mean that you can use it without paying a licensing fee.
16 *
17 * Knowledge of the source code may NOT be used to develop a similar product.
18 *
19 * Please help us continue to provide the Embedded community with the finest
20 * software available. Your honesty is greatly appreciated.
21 *********************************************************************************************************
22 */
23 
24 /*
25 *********************************************************************************************************
26 *
27 * ASCII STRING MANAGEMENT
28 *
29 * Filename : lib_str.c
30 * Version : V1.30
31 * Programmer(s) : ITJ
32 * BAN
33 * JDH
34 *********************************************************************************************************
35 * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software.
36 *
37 * (a) ALL standard library functions are implemented in the custom library modules :
38 *
39 * (1) <Custom Library Directory>\lib*.*
40 *
41 * (2) <Custom Library Directory>\Ports<cpu><compiler>\lib*_a.*
42 *
43 * where
44 * <Custom Library Directory> directory path for custom library software
45 * <cpu> directory name for specific processor (CPU)
46 * <compiler> directory name for specific compiler
47 *
48 * (b) Product-specific library functions are implemented in individual products.
49 *
50 *********************************************************************************************************
51 * Notice(s) : (1) The Institute of Electrical and Electronics Engineers and The Open Group, have given
52 * us permission to reprint portions of their documentation. Portions of this text are
53 * reprinted and reproduced in electronic form from the IEEE Std 1003.1, 2004 Edition,
54 * Standard for Information Technology -- Portable Operating System Interface (POSIX),
55 * The Open Group Base Specifications Issue 6, Copyright (C) 2001-2004 by the Institute
56 * of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any
57 * discrepancy between these versions and the original IEEE and The Open Group Standard,
58 * the original IEEE and The Open Group Standard is the referee document. The original
59 * Standard can be obtained online at http://www.opengroup.org/unix/online.html.
60 *********************************************************************************************************
61 */
62 
63 
64 /*
65 *********************************************************************************************************
66 * INCLUDE FILES
67 *********************************************************************************************************
68 */
69 
70 #define LIB_STR_MODULE
71 #include <lib_str.h>
72 
73 
74 /*$PAGE*/
75 /*
76 *********************************************************************************************************
77 * LOCAL DEFINES
78 *********************************************************************************************************
79 */
80 
81 
82 /*
83 *********************************************************************************************************
84 * LOCAL CONSTANTS
85 *********************************************************************************************************
86 */
87 
88 
89 /*
90 *********************************************************************************************************
91 * LOCAL DATA TYPES
92 *********************************************************************************************************
93 */
94 
95 
96 /*
97 *********************************************************************************************************
98 * LOCAL TABLES
99 *********************************************************************************************************
100 */
101 
103  (CPU_INT32U) DEF_INT_32U_MAX_VAL, /* Invalid base 0. */
104  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 1)), /* Invalid base 1. */
105  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 2)), /* 32-bit mult ovf th for base 2. */
106  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 3)), /* 32-bit mult ovf th for base 3. */
107  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 4)), /* 32-bit mult ovf th for base 4. */
108  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 5)), /* 32-bit mult ovf th for base 5. */
109  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 6)), /* 32-bit mult ovf th for base 6. */
110  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 7)), /* 32-bit mult ovf th for base 7. */
111  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 8)), /* 32-bit mult ovf th for base 8. */
112  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 9)), /* 32-bit mult ovf th for base 9. */
113  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 10)), /* 32-bit mult ovf th for base 10. */
114  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 11)), /* 32-bit mult ovf th for base 11. */
115  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 12)), /* 32-bit mult ovf th for base 12. */
116  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 13)), /* 32-bit mult ovf th for base 13. */
117  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 14)), /* 32-bit mult ovf th for base 14. */
118  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 15)), /* 32-bit mult ovf th for base 15. */
119  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 16)), /* 32-bit mult ovf th for base 16. */
120  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 17)), /* 32-bit mult ovf th for base 17. */
121  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 18)), /* 32-bit mult ovf th for base 18. */
122  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 19)), /* 32-bit mult ovf th for base 19. */
123  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 20)), /* 32-bit mult ovf th for base 20. */
124  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 21)), /* 32-bit mult ovf th for base 21. */
125  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 22)), /* 32-bit mult ovf th for base 22. */
126  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 23)), /* 32-bit mult ovf th for base 23. */
127  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 24)), /* 32-bit mult ovf th for base 24. */
128  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 25)), /* 32-bit mult ovf th for base 25. */
129  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 26)), /* 32-bit mult ovf th for base 26. */
130  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 27)), /* 32-bit mult ovf th for base 27. */
131  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 28)), /* 32-bit mult ovf th for base 28. */
132  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 29)), /* 32-bit mult ovf th for base 29. */
133  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 30)), /* 32-bit mult ovf th for base 30. */
134  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 31)), /* 32-bit mult ovf th for base 31. */
135  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 32)), /* 32-bit mult ovf th for base 32. */
136  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 33)), /* 32-bit mult ovf th for base 33. */
137  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 34)), /* 32-bit mult ovf th for base 34. */
138  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 35)), /* 32-bit mult ovf th for base 35. */
139  ((CPU_INT32U)(DEF_INT_32U_MAX_VAL / 36)) /* 32-bit mult ovf th for base 36. */
140 };
141 
142 
143 /*
144 *********************************************************************************************************
145 * LOCAL GLOBAL VARIABLES
146 *********************************************************************************************************
147 */
148 
149 
150 /*$PAGE*/
151 /*
152 *********************************************************************************************************
153 * LOCAL FUNCTION PROTOTYPES
154 *********************************************************************************************************
155 */
156 
158  CPU_INT08U nbr_dig,
159  CPU_INT08U nbr_base,
160  CPU_BOOLEAN nbr_neg,
161  CPU_CHAR lead_char,
162  CPU_BOOLEAN lower_case,
163  CPU_BOOLEAN nul,
164  CPU_CHAR *pstr);
165 
167  CPU_CHAR **pstr_next,
168  CPU_INT08U nbr_base,
169  CPU_BOOLEAN nbr_signed,
170  CPU_BOOLEAN *pnbr_neg);
171 
172 
173 /*
174 *********************************************************************************************************
175 * LOCAL CONFIGURATION ERRORS
176 *********************************************************************************************************
177 */
178 
179 
180 /*$PAGE*/
181 /*
182 *********************************************************************************************************
183 * Str_Len()
184 *
185 * Description : Calculate length of a string.
186 *
187 * Argument(s) : pstr Pointer to string (see Note #1).
188 *
189 * Return(s) : Length of string; number of characters in string before terminating NULL character.
190 *
191 * Caller(s) : Application.
192 *
193 * Note(s) : (1) String buffer NOT modified.
194 *
195 * (2) String length calculation terminates when :
196 *
197 * (a) String pointer points to NULL.
198 * (1) String buffer overlaps with NULL address.
199 * (2) String length calculated for string up to but NOT beyond or including
200 * the NULL address.
201 *
202 * (b) Terminating NULL character found.
203 * (1) String length calculated for string up to but NOT including
204 * the NULL character.
205 *********************************************************************************************************
206 */
207 
209 {
210  CPU_SIZE_T len;
211 
212 
213  len = Str_Len_N((CPU_CHAR *)pstr,
215 
216  return (len);
217 }
218 
219 
220 /*$PAGE*/
221 /*
222 *********************************************************************************************************
223 * Str_Len_N()
224 *
225 * Description : Calculate length of a string, up to a maximum number of characters.
226 *
227 * Argument(s) : pstr Pointer to string (see Note #1).
228 *
229 * len_max Maximum number of characters to search (see Note #2c).
230 *
231 * Return(s) : Length of string; number of characters in string before terminating NULL character,
232 * if terminating NULL character found.
233 *
234 * Requested maximum number of characters to search,
235 * if terminating NULL character NOT found.
236 *
237 * Caller(s) : Application.
238 *
239 * Note(s) : (1) String buffer NOT modified.
240 *
241 * (2) String length calculation terminates when :
242 *
243 * (a) String pointer points to NULL.
244 * (1) String buffer overlaps with NULL address.
245 * (2) String length calculated for string up to but NOT beyond or including
246 * the NULL address.
247 *
248 * (b) Terminating NULL character found.
249 * (1) String length calculated for string up to but NOT including
250 * the NULL character.
251 *
252 * (c) 'len_max' number of characters searched.
253 * (1) 'len_max' number of characters does NOT include the terminating NULL character.
254 *********************************************************************************************************
255 */
256 
258  CPU_SIZE_T len_max)
259 {
260  CPU_SIZE_T len;
261 
262 
263  len = 0;
264  while (( pstr != (CPU_CHAR *) 0 ) && /* Calc str len until NULL ptr (see Note #2a) ... */
265  (*pstr != (CPU_CHAR )'\0') && /* ... or NULL char found (see Note #2b) ... */
266  ( len < (CPU_SIZE_T)len_max)) { /* ... or max nbr chars srch'd (see Note #2c). */
267  len++;
268  pstr++;
269  }
270 
271  return (len);
272 }
273 
274 
275 /*$PAGE*/
276 /*
277 *********************************************************************************************************
278 * Str_Copy()
279 *
280 * Description : Copy source string to destination string buffer.
281 *
282 * Argument(s) : pdest Pointer to destination string buffer to receive source string copy (see Note #1).
283 *
284 * psrc Pointer to source string to copy into destination string buffer.
285 *
286 * Return(s) : Pointer to destination string, if NO errors (see Note #2).
287 *
288 * Pointer to NULL, otherwise.
289 *
290 * Caller(s) : Application.
291 *
292 * Note(s) : (1) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
293 *
294 * (a) Destination buffer size MUST be large enough to accommodate the entire source
295 * string size including the terminating NULL character.
296 *
297 * (2) String copy terminates when :
298 *
299 * (a) Destination/Source string pointer(s) are passed NULL pointers.
300 * (1) No string copy performed; NULL pointer returned.
301 *
302 * (b) Destination/Source string pointer(s) points to NULL.
303 * (1) String buffer(s) overlap with NULL address.
304 * (2) Source string copied into destination string buffer up to but NOT beyond or
305 * including the NULL address; destination string buffer properly terminated
306 * with NULL character.
307 *
308 * (c) Source string's terminating NULL character found.
309 * (1) Entire source string copied into destination string buffer.
310 *********************************************************************************************************
311 */
312 
314  CPU_CHAR *psrc)
315 {
316  pdest = Str_Copy_N((CPU_CHAR *)pdest,
317  (CPU_CHAR *)psrc,
319 
320  return (pdest);
321 }
322 
323 
324 /*$PAGE*/
325 /*
326 *********************************************************************************************************
327 * Str_Copy_N()
328 *
329 * Description : Copy source string to destination string buffer, up to a maximum number of characters.
330 *
331 * Argument(s) : pdest Pointer to destination string buffer to receive source string copy (see Note #1).
332 *
333 * psrc Pointer to source string to copy into destination string buffer.
334 *
335 * len_max Maximum number of characters to copy (see Note #2d).
336 *
337 * Return(s) : Pointer to destination string, if NO errors (see Note #2).
338 *
339 * Pointer to NULL, otherwise.
340 *
341 * Caller(s) : Application.
342 *
343 * Note(s) : (1) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller.
344 *
345 * (a) Destination buffer size MUST be large enough to accommodate the entire source
346 * string size including the terminating NULL character.
347 *
348 * (2) String copy terminates when :
349 *
350 * (a) Destination/Source string pointer(s) are passed NULL pointers.
351 * (1) No string copy performed; NULL pointer returned.
352 *
353 * (b) Destination/Source string pointer(s) points to NULL.
354 * (1) String buffer(s) overlap with NULL address.
355 * (2) Source string copied into destination string buffer up to but NOT beyond or
356 * including the NULL address; destination string buffer properly terminated
357 * with NULL character.
358 *
359 * (c) Source string's terminating NULL character found.
360 * (1) Entire source string copied into destination string buffer.
361 *
362 * (d) 'len_max' number of characters copied.
363 * (1) 'len_max' number of characters does NOT include the terminating NULL character.
364 *
365 * See also Note #1a.
366 *********************************************************************************************************
367 */
368 
370  CPU_CHAR *psrc,
371  CPU_SIZE_T len_max)
372 {
373  CPU_CHAR *pstr;
374  CPU_CHAR *pstr_next;
375  CPU_SIZE_T len_copy;
376 
377  /* Rtn NULL if str ptr(s) NULL (see Note #2a). */
378  if (pdest == (CPU_CHAR *)0) {
379  return ((CPU_CHAR *)0);
380  }
381  if (psrc == (CPU_CHAR *)0) {
382  return ((CPU_CHAR *)0);
383  }
384 
385  if (len_max == (CPU_SIZE_T)0) { /* Rtn NULL if copy len equals zero (see Note #2d). */
386  return ((CPU_CHAR *)0);
387  }
388 
389 
390  pstr = pdest;
391  pstr_next = pstr;
392  pstr_next++;
393  len_copy = 0;
394 
395  while (( pstr_next != (CPU_CHAR *) 0 ) && /* Copy str until NULL ptr(s) [see Note #2b] ... */
396  ( psrc != (CPU_CHAR *) 0 ) &&
397  (*psrc != (CPU_CHAR )'\0') && /* ... or NULL char found (see Note #2c); ... */
398  ( len_copy < (CPU_SIZE_T)len_max)) { /* ... or max nbr chars copied (see Note #2d). */
399  *pstr = *psrc;
400  pstr++;
401  pstr_next++;
402  psrc++;
403  len_copy++;
404  }
405 
406  *pstr = (CPU_CHAR)'\0'; /* Append NULL char (see Note #2b2). */
407 
408 
409  return (pdest);
410 }
411 
412 
413 /*$PAGE*/
414 /*
415 *********************************************************************************************************
416 * Str_Cat()
417 *
418 * Description : Append concatenation string to destination string.
419 *
420 * Argument(s) : pdest Pointer to destination string to append concatenation string (see Note #1).
421 *
422 * pstr_cat Pointer to concatenation string to append to destination string.
423 *
424 * Return(s) : Pointer to destination string, if NO errors (see Note #2).
425 *
426 * Pointer to NULL, otherwise.
427 *
428 * Caller(s) : Application.
429 *
430 * Note(s) : (1) Destination string buffer size NOT validated; buffer overruns MUST be prevented by caller.
431 *
432 * (a) Destination buffer size MUST be large enough to accommodate the entire concatenated
433 * string size including the terminating NULL character.
434 *
435 * (2) String concatenation terminates when :
436 *
437 * (a) Destination/Concatenation string pointer(s) are passed NULL pointers.
438 * (1) No string concatenation performed; NULL pointer returned.
439 *
440 * (b) Destination string overlaps with NULL address.
441 * (1) No string concatenation performed; NULL pointer returned.
442 *
443 * (c) Destination/Concatenation string pointer(s) points to NULL.
444 * (1) String buffer(s) overlap with NULL address.
445 * (2) Concatenation string appended into destination string buffer up to but NOT
446 * beyond or including the NULL address; destination string buffer properly
447 * terminated with NULL character.
448 *
449 * (d) Concatenation string's terminating NULL character found.
450 * (1) Entire concatenation string appended to destination string.
451 *********************************************************************************************************
452 */
453 
455  CPU_CHAR *pstr_cat)
456 {
457  pdest = Str_Cat_N((CPU_CHAR *)pdest,
458  (CPU_CHAR *)pstr_cat,
460 
461  return (pdest);
462 }
463 
464 
465 /*$PAGE*/
466 /*
467 *********************************************************************************************************
468 * Str_Cat_N()
469 *
470 * Description : Append concatenation string to destination string, up to a maximum number of characters.
471 *
472 * Argument(s) : pdest Pointer to destination string to append concatenation string (see Note #1).
473 *
474 * pstr_cat Pointer to concatenation string to append to destination string.
475 *
476 * len_max Maximum number of characters to concatenate (see Note #2e).
477 *
478 * Return(s) : Pointer to destination string, if NO errors (see Note #2).
479 *
480 * Pointer to NULL, otherwise.
481 *
482 * Caller(s) : Application.
483 *
484 * Note(s) : (1) Destination string buffer size NOT validated; buffer overruns MUST be prevented by caller.
485 *
486 * (a) Destination buffer size MUST be large enough to accommodate the entire concatenated
487 * string size including the terminating NULL character.
488 *
489 * (2) String concatenation terminates when :
490 *
491 * (a) Destination/Concatenation string pointer(s) are passed NULL pointers.
492 * (1) No string concatenation performed; NULL pointer returned.
493 *
494 * (b) Destination string overlaps with NULL address.
495 * (1) No string concatenation performed; NULL pointer returned.
496 *
497 * (c) Destination/Concatenation string pointer(s) points to NULL.
498 * (1) String buffer(s) overlap with NULL address.
499 * (2) Concatenation string appended into destination string buffer up to but NOT
500 * beyond or including the NULL address; destination string buffer properly
501 * terminated with NULL character.
502 *
503 * (d) Concatenation string's terminating NULL character found.
504 * (1) Entire concatenation string appended to destination string.
505 *
506 * (e) 'len_max' number of characters concatenated.
507 * (1) 'len_max' number of characters does NOT include the terminating NULL character.
508 *
509 * See also Note #1a.
510 *********************************************************************************************************
511 */
512 /*$PAGE*/
514  CPU_CHAR *pstr_cat,
515  CPU_SIZE_T len_max)
516 {
517  CPU_CHAR *pstr;
518  CPU_CHAR *pstr_next;
519  CPU_SIZE_T len_cat;
520 
521  /* Rtn NULL if str ptr(s) NULL (see Note #2a). */
522  if (pdest == (CPU_CHAR *)0) {
523  return ((CPU_CHAR *)0);
524  }
525  if (pstr_cat == (CPU_CHAR *)0) {
526  return ((CPU_CHAR *)0);
527  }
528 
529  if (len_max == (CPU_SIZE_T)0) { /* Rtn NULL if cat len equals zero (see Note #2e). */
530  return ((CPU_CHAR *)0);
531  }
532 
533 
534  pstr = pdest;
535  while (( pstr != (CPU_CHAR *) 0 ) && /* Adv to end of cur dest str until NULL ptr ... */
536  (*pstr != (CPU_CHAR )'\0')) { /* ... or NULL char found.. */
537  pstr++;
538  }
539  if (pstr == (CPU_CHAR *)0) { /* If NULL str overrun, rtn NULL (see Note #2b). */
540  return ((CPU_CHAR *)0);
541  }
542 
543  pstr_next = pstr;
544  pstr_next++;
545  len_cat = 0;
546 
547  while (( pstr_next != (CPU_CHAR *) 0 ) && /* Cat str until NULL ptr(s) [see Note #2c] ... */
548  ( pstr_cat != (CPU_CHAR *) 0 ) &&
549  (*pstr_cat != (CPU_CHAR )'\0') && /* ... or NULL char found (see Note #2d); ... */
550  ( len_cat < (CPU_SIZE_T)len_max)) { /* ... or max nbr chars cat'd (see Note #2d). */
551  *pstr = *pstr_cat;
552  pstr++;
553  pstr_next++;
554  pstr_cat++;
555  len_cat++;
556  }
557 
558  *pstr = (CPU_CHAR)'\0'; /* Append NULL char (see Note #2c2). */
559 
560 
561  return (pdest);
562 }
563 
564 
565 /*$PAGE*/
566 /*
567 *********************************************************************************************************
568 * Str_Cmp()
569 *
570 * Description : Determine if two strings are identical.
571 *
572 * Argument(s) : p1_str Pointer to first string (see Note #1).
573 *
574 * p2_str Pointer to second string (see Note #1).
575 *
576 * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, #3b, & #3d).
577 *
578 * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
579 *
580 * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
581 *
582 * See also Note #2b.
583 *
584 * Caller(s) : Application.
585 *
586 * Note(s) : (1) String buffers NOT modified.
587 *
588 * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' states that "the
589 * strcmp() function shall compare the string pointed to by s1 to the string pointed
590 * to by s2".
591 *
592 * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : RETURN VALUE' states that
593 * "upon successful completion, strncmp() shall return an integer greater than,
594 * equal to, or less than 0".
595 *
596 * (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
597 * sign of a non-zero return value shall be determined by the sign of the difference
598 * between the values of the first pair of bytes ... that differ in the strings
599 * being compared".
600 *
601 * (3) String comparison terminates when :
602 *
603 * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
604 * (1) NULL strings identical; return 0.
605 *
606 * (B) (1) 'p1_str' passed a NULL pointer.
607 * (a) Return negative value of character pointed to by 'p2_str'.
608 *
609 * (2) 'p2_str' passed a NULL pointer.
610 * (a) Return positive value of character pointed to by 'p1_str'.
611 *
612 * (2) (A) BOTH strings point to NULL.
613 * (1) Strings overlap with NULL address.
614 * (2) Strings identical up to but NOT beyond or including the NULL address;
615 * return 0.
616 *
617 * (B) (1) 'p1_str_next' points to NULL.
618 * (a) 'p1_str' overlaps with NULL address.
619 * (b) Strings compared up to but NOT beyond or including the NULL address.
620 * (c) Return negative value of character pointed to by 'p2_str_next'.
621 *
622 * (2) 'p2_str_next' points to NULL.
623 * (a) 'p2_str' overlaps with NULL address.
624 * (b) Strings compared up to but NOT beyond or including the NULL address.
625 * (c) Return positive value of character pointed to by 'p1_str_next'.
626 *
627 * (b) Terminating NULL character found in both strings.
628 * (1) Strings identical; return 0.
629 * (2) Only one NULL character test required in conditional since previous condition
630 * tested character equality.
631 *
632 * (c) Non-matching characters found.
633 * (1) Return signed-integer difference of the character pointed to by 'p2_str'
634 * from the character pointed to by 'p1_str'.
635 *
636 * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
637 * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
638 *********************************************************************************************************
639 */
640 
642  CPU_CHAR *p2_str)
643 {
644  CPU_INT16S cmp_val;
645 
646 
647  cmp_val = Str_Cmp_N((CPU_CHAR *)p1_str,
648  (CPU_CHAR *)p2_str,
650 
651  return (cmp_val);
652 }
653 
654 
655 /*$PAGE*/
656 /*
657 *********************************************************************************************************
658 * Str_Cmp_N()
659 *
660 * Description : Determine if two strings are identical for up to a maximum number of characters.
661 *
662 * Argument(s) : p1_str Pointer to first string (see Note #1).
663 *
664 * p2_str Pointer to second string (see Note #1).
665 *
666 * len_max Maximum number of characters to compare (see Note #3d).
667 *
668 * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, #3b, & #3d).
669 *
670 * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
671 *
672 * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
673 *
674 * See also Note #2b.
675 *
676 * Caller(s) : Application.
677 *
678 * Note(s) : (1) String buffers NOT modified.
679 *
680 * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : DESCRIPTION' states that :
681 *
682 * (1) "The strncmp() function shall compare ... the array pointed to by s1 to the
683 * array pointed to by s2" but ...
684 * (2) "not more than 'n' bytes" of either array.
685 *
686 * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : RETURN VALUE' states that
687 * "upon successful completion, strncmp() shall return an integer greater than,
688 * equal to, or less than 0".
689 *
690 * (2) IEEE Std 1003.1, 2004 Edition, Section 'strncmp() : DESCRIPTION' adds that
691 * "the sign of a non-zero return value is determined by the sign of the difference
692 * between the values of the first pair of bytes ... that differ in the strings
693 * being compared".
694 *
695 * (3) String comparison terminates when :
696 *
697 * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
698 * (1) NULL strings identical; return 0.
699 *
700 * (B) (1) 'p1_str' passed a NULL pointer.
701 * (a) Return negative value of character pointed to by 'p2_str'.
702 *
703 * (2) 'p2_str' passed a NULL pointer.
704 * (a) Return positive value of character pointed to by 'p1_str'.
705 *
706 * (2) (A) BOTH strings point to NULL.
707 * (1) Strings overlap with NULL address.
708 * (2) Strings identical up to but NOT beyond or including the NULL address;
709 * return 0.
710 *
711 * (B) (1) 'p1_str_next' points to NULL.
712 * (a) 'p1_str' overlaps with NULL address.
713 * (b) Strings compared up to but NOT beyond or including the NULL address.
714 * (c) Return negative value of character pointed to by 'p2_str_next'.
715 *
716 * (2) 'p2_str_next' points to NULL.
717 * (a) 'p2_str' overlaps with NULL address.
718 * (b) Strings compared up to but NOT beyond or including the NULL address.
719 * (c) Return positive value of character pointed to by 'p1_str_next'.
720 *
721 * (b) Terminating NULL character found in both strings.
722 * (1) Strings identical; return 0.
723 * (2) Only one NULL character test required in conditional since previous condition
724 * tested character equality.
725 *
726 * (c) Non-matching characters found.
727 * (1) Return signed-integer difference of the character pointed to by 'p2_str'
728 * from the character pointed to by 'p1_str'.
729 *
730 * (d) (1) 'len_max' passed a zero length.
731 * (A) Zero-length strings identical; return 0.
732 *
733 * (2) First 'len_max' number of characters identical.
734 * (A) Strings identical; return 0.
735 *
736 * See also Note #2a2.
737 *
738 * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
739 * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
740 *********************************************************************************************************
741 */
742 /*$PAGE*/
744  CPU_CHAR *p2_str,
745  CPU_SIZE_T len_max)
746 {
747  CPU_CHAR *p1_str_next;
748  CPU_CHAR *p2_str_next;
749  CPU_INT16S cmp_val;
750  CPU_SIZE_T cmp_len;
751 
752 
753  if (len_max == 0) { /* If cmp len equals zero, rtn 0 (see Note #3d1). */
754  return ((CPU_INT16S)0);
755  }
756 
757  if (p1_str == (CPU_CHAR *)0) {
758  if (p2_str == (CPU_CHAR *)0) {
759  return ((CPU_INT16S)0); /* If BOTH str ptrs NULL, rtn 0 (see Note #3a1A). */
760  }
761  cmp_val = (CPU_INT16S)0 - (CPU_INT16S)(*p2_str);
762  return (cmp_val); /* If p1_str NULL, rtn neg p2_str val (see Note #3a1B1).*/
763  }
764  if (p2_str == (CPU_CHAR *)0) {
765  cmp_val = (CPU_INT16S)(*p1_str);
766  return (cmp_val); /* If p2_str NULL, rtn pos p1_str val (see Note #3a1B2).*/
767  }
768 
769 
770  p1_str_next = p1_str;
771  p2_str_next = p2_str;
772  p1_str_next++;
773  p2_str_next++;
774  cmp_len = 0;
775  while ((*p1_str == *p2_str) && /* Cmp strs until non-matching chars (see Note #3c) ... */
776  (*p1_str != (CPU_CHAR )'\0') && /* ... or NULL chars (see Note #3b) ... */
777  ( p1_str_next != (CPU_CHAR *) 0 ) && /* ... or NULL ptr(s) found (see Note #3a2); */
778  ( p2_str_next != (CPU_CHAR *) 0 ) &&
779  ( cmp_len < (CPU_SIZE_T)len_max)) { /* ... or max nbr chars cmp'd (see Note #3d2). */
780  p1_str_next++;
781  p2_str_next++;
782  p1_str++;
783  p2_str++;
784  cmp_len++;
785  }
786 
787 
788  if (cmp_len == len_max) { /* If strs identical for len nbr of chars, ... */
789  return ((CPU_INT16S)0); /* ... rtn 0 (see Note #3d2). */
790  }
791 
792  if (*p1_str != *p2_str) { /* If strs NOT identical, ... */
793  cmp_val = (CPU_INT16S)(*p1_str) - (CPU_INT16S)(*p2_str); /* ... calc & rtn char diff (see Note #3c). */
794 
795  } else if (*p1_str == (CPU_CHAR)'\0') { /* If NULL char(s) found, ... */
796  cmp_val = 0; /* ... strs identical; rtn 0 (see Note #3b). */
797 
798  } else {
799  if (p1_str_next == (CPU_CHAR *)0) {
800  if (p2_str_next == (CPU_CHAR *)0) { /* If BOTH next str ptrs NULL, ... */
801  cmp_val = (CPU_INT16S)0; /* ... rtn 0 (see Note #3a2A). */
802  } else { /* If p1_str_next NULL, ... */
803  /* ... rtn neg p2_str_next val (see Note #3a2B1). */
804  cmp_val = (CPU_INT16S)0 - (CPU_INT16S)(*p2_str_next);
805  }
806  } else { /* If p2_str_next NULL, ... */
807  cmp_val = (CPU_INT16S)(*p1_str_next); /* ... rtn pos p1_str_next val (see Note #3a2B2). */
808  }
809  }
810 
811 
812  return (cmp_val);
813 }
814 
815 
816 /*$PAGE*/
817 /*
818 *********************************************************************************************************
819 * Str_CmpIgnoreCase()
820 *
821 * Description : Determine if two strings are identical, ignoring case.
822 *
823 * Argument(s) : p1_str Pointer to first string (see Note #1).
824 *
825 * p2_str Pointer to second string (see Note #1).
826 *
827 * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, #3b, & #3d).
828 *
829 * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
830 *
831 * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
832 *
833 * See also Note #2b.
834 *
835 * Caller(s) : Application.
836 *
837 * Note(s) : (1) String buffers NOT modified.
838 *
839 * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strcasecmp() : DESCRIPTION' states that :
840 *
841 * (1) (A) "The strcasecmp() function shall compare ... the string pointed to by s1
842 * to the string pointed to by s2" ...
843 * (B) "ignoring differences in case".
844 *
845 * (2) "strcasecmp() ... shall behave as if the strings had been converted to lowercase
846 * and then a byte comparison performed."
847 *
848 * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strcasecmp() : RETURN VALUE' states that
849 * "upon successful completion, strcasecmp() shall return an integer greater than,
850 * equal to, or less than 0".
851 *
852 * (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
853 * sign of a non-zero return value shall be determined by the sign of the difference
854 * between the values of the first pair of bytes ... that differ in the strings
855 * being compared".
856 *
857 * (3) String comparison terminates when :
858 *
859 * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
860 * (1) NULL strings identical; return 0.
861 *
862 * (B) (1) 'p1_str' passed a NULL pointer.
863 * (a) Return negative value of character pointed to by 'p2_str', converted
864 * to lower case (see Note #2a2).
865 *
866 * (2) 'p2_str' passed a NULL pointer.
867 * (a) Return positive value of character pointed to by 'p1_str', converted
868 * to lower case (see Note #2a2).
869 *
870 * (2) (A) BOTH strings point to NULL.
871 * (1) Strings overlap with NULL address.
872 * (2) Strings identical up to but NOT beyond or including the NULL address;
873 * return 0.
874 *
875 * (B) (1) 'p1_str_next' points to NULL.
876 * (a) 'p1_str' overlaps with NULL address.
877 * (b) Strings compared up to but NOT beyond or including the NULL address.
878 * (c) Return negative value of character pointed to by 'p2_str_next',
879 * converted to lower case (see Note #2a2).
880 *
881 * (2) 'p2_str_next' points to NULL.
882 * (a) 'p2_str' overlaps with NULL address.
883 * (b) Strings compared up to but NOT beyond or including the NULL address.
884 * (c) Return positive value of character pointed to by 'p1_str_next',
885 * converted to lower case (see Note #2a2).
886 *
887 * (b) Terminating NULL character found in both strings.
888 * (1) Strings identical; return 0.
889 * (2) Only one NULL character test required in conditional since previous condition
890 * tested character equality.
891 *
892 * (c) Non-matching characters found.
893 * (1) Return signed-integer difference of the character pointed to by 'p2_str',
894 * converted to lower case, from the character pointed to by 'p1_str', converted
895 * to lower case.
896 *
897 * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
898 * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
899 *********************************************************************************************************
900 */
901 /*$PAGE*/
903  CPU_CHAR *p2_str)
904 {
905  CPU_INT16S cmp_val;
906 
907 
908  cmp_val = Str_CmpIgnoreCase_N((CPU_CHAR *)p1_str,
909  (CPU_CHAR *)p2_str,
911 
912  return (cmp_val);
913 }
914 
915 
916 /*$PAGE*/
917 /*
918 *********************************************************************************************************
919 * Str_CmpIgnoreCase_N()
920 *
921 * Description : Determine if two strings are identical for up to a maximum number of characters,
922 * ignoring case.
923 *
924 * Argument(s) : p1_str Pointer to first string (see Note #1).
925 *
926 * p2_str Pointer to second string (see Note #1).
927 *
928 * len_max Maximum number of characters to compare (see Note #3d).
929 *
930 * Return(s) : 0, if strings are identical (see Notes #3a1A, #3a2A, #3b, & #3d).
931 *
932 * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #3a1B1, #3a2B1, & #3c).
933 *
934 * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #3a1B2, #3a2B2, & #3c).
935 *
936 * See also Note #2b.
937 *
938 * Caller(s) : Application.
939 *
940 * Note(s) : (1) String buffers NOT modified.
941 *
942 * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strncasecmp() : DESCRIPTION' states that :
943 *
944 * (1) (A) "The strncasecmp() function shall compare ... the string pointed to by s1
945 * to the string pointed to by s2" ...
946 * (B) "ignoring differences in case" & ...
947 * (C) "not more than 'n' bytes" of either string.
948 *
949 * (2) "strncasecmp() shall behave as if the strings had been converted to lowercase
950 * and then a byte comparison performed."
951 *
952 * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strncasecmp() : RETURN VALUE' states that
953 * "upon successful completion, strncasecmp() shall return an integer greater than,
954 * equal to, or less than 0".
955 *
956 * (2) IEEE Std 1003.1, 2004 Edition, Section 'strcmp() : DESCRIPTION' adds that "the
957 * sign of a non-zero return value shall be determined by the sign of the difference
958 * between the values of the first pair of bytes ... that differ in the strings
959 * being compared".
960 *
961 * (3) String comparison terminates when :
962 *
963 * (a) (1) (A) BOTH string pointer(s) are passed NULL pointers.
964 * (1) NULL strings identical; return 0.
965 *
966 * (B) (1) 'p1_str' passed a NULL pointer.
967 * (a) Return negative value of character pointed to by 'p2_str', converted
968 * to lower case (see Note #2a2).
969 *
970 * (2) 'p2_str' passed a NULL pointer.
971 * (a) Return positive value of character pointed to by 'p1_str', converted
972 * to lower case (see Note #2a2).
973 *
974 * (2) (A) BOTH strings point to NULL.
975 * (1) Strings overlap with NULL address.
976 * (2) Strings identical up to but NOT beyond or including the NULL address;
977 * return 0.
978 *
979 * (B) (1) 'p1_str_next' points to NULL.
980 * (a) 'p1_str' overlaps with NULL address.
981 * (b) Strings compared up to but NOT beyond or including the NULL address.
982 * (c) Return negative value of character pointed to by 'p2_str_next',
983 * converted to lower case (see Note #2a2).
984 *
985 * (2) 'p2_str_next' points to NULL.
986 * (a) 'p2_str' overlaps with NULL address.
987 * (b) Strings compared up to but NOT beyond or including the NULL address.
988 * (c) Return positive value of character pointed to by 'p1_str_next',
989 * converted to lower case (see Note #2a2).
990 *
991 * (b) Terminating NULL character found in both strings.
992 * (1) Strings identical; return 0.
993 * (2) Only one NULL character test required in conditional since previous condition
994 * tested character equality.
995 *
996 * (c) Non-matching characters found.
997 * (1) Return signed-integer difference of the character pointed to by 'p2_str',
998 * converted to lower case, from the character pointed to by 'p1_str', converted
999 * to lower case.
1000 *
1001 * (d) (1) 'len_max' passed a zero length.
1002 * (A) Zero-length strings identical; return 0.
1003 *
1004 * (2) First 'len_max' number of characters identical.
1005 * (A) Strings identical; return 0.
1006 *
1007 * See also Note #2a1C.
1008 *$PAGE*
1009 * (4) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison
1010 * return value, 'CPU_CHAR' native data type size MUST be 8-bit.
1011 *********************************************************************************************************
1012 */
1013 
1015  CPU_CHAR *p2_str,
1016  CPU_SIZE_T len_max)
1017 {
1018  CPU_CHAR *p1_str_next;
1019  CPU_CHAR *p2_str_next;
1020  CPU_CHAR char1;
1021  CPU_CHAR char2;
1022  CPU_INT16S cmp_val;
1023  CPU_SIZE_T cmp_len;
1024 
1025 
1026  if (len_max == 0) { /* If cmp len equals zero, rtn 0 (see Note #3d1). */
1027  return ((CPU_INT16S)0);
1028  }
1029 
1030  if (p1_str == (CPU_CHAR *)0) {
1031  if (p2_str == (CPU_CHAR *)0) {
1032  return ((CPU_INT16S)0); /* If BOTH str ptrs NULL, rtn 0 (see Note #3a1A). */
1033  }
1034  char2 = ASCII_TO_LOWER(*p2_str);
1035  cmp_val = (CPU_INT16S)0 - (CPU_INT16S)char2;
1036  return (cmp_val); /* If p1_str NULL, rtn neg p2_str val (see Note #3a1B1).*/
1037  }
1038  if (p2_str == (CPU_CHAR *)0) {
1039  char1 = ASCII_TO_LOWER(*p1_str);
1040  cmp_val = (CPU_INT16S)char1;
1041  return (cmp_val); /* If p2_str NULL, rtn pos p1_str val (see Note #3a1B2).*/
1042  }
1043 
1044 
1045  p1_str_next = p1_str;
1046  p2_str_next = p2_str;
1047  p1_str_next++;
1048  p2_str_next++;
1049  char1 = ASCII_TO_LOWER(*p1_str);
1050  char2 = ASCII_TO_LOWER(*p2_str);
1051  cmp_len = 0;
1052  while (( char1 == char2) && /* Cmp strs until non-matching chars (see Note #3c) ... */
1053  (*p1_str != (CPU_CHAR )'\0') && /* ... or NULL chars (see Note #3b) ... */
1054  ( p1_str_next != (CPU_CHAR *) 0 ) && /* ... or NULL ptr(s) found (see Note #3a2); */
1055  ( p2_str_next != (CPU_CHAR *) 0 ) &&
1056  ( cmp_len < (CPU_SIZE_T)len_max)) { /* ... or max nbr chars cmp'd (see Note #3d2). */
1057  p1_str_next++;
1058  p2_str_next++;
1059  p1_str++;
1060  p2_str++;
1061  cmp_len++;
1062  char1 = ASCII_TO_LOWER(*p1_str);
1063  char2 = ASCII_TO_LOWER(*p2_str);
1064  }
1065 
1066 
1067  if (cmp_len == len_max) { /* If strs identical for len nbr of chars, ... */
1068  return ((CPU_INT16S)0); /* ... rtn 0 (see Note #3d2). */
1069  }
1070 
1071  if (char1 != char2) { /* If strs NOT identical, ... */
1072  cmp_val = (CPU_INT16S)char1 - (CPU_INT16S)char2; /* ... calc & rtn char diff (see Note #3c). */
1073 
1074  } else if (char1 == (CPU_CHAR)'\0') { /* If NULL char(s) found, ... */
1075  cmp_val = 0; /* ... strs identical; rtn 0 (see Note #3b). */
1076 
1077  } else {
1078  if (p1_str_next == (CPU_CHAR *)0) {
1079  if (p2_str_next == (CPU_CHAR *)0) { /* If BOTH next str ptrs NULL, ... */
1080  cmp_val = (CPU_INT16S)0; /* ... rtn 0 (see Note #3a2A). */
1081  } else { /* If p1_str_next NULL, ... */
1082  char2 = ASCII_TO_LOWER(*p2_str_next);
1083  cmp_val = (CPU_INT16S)0 - (CPU_INT16S)char2; /* ... rtn neg p2_str_next val (see Note #3a2B1). */
1084  }
1085  } else { /* If p2_str_next NULL, ... */
1086  char1 = ASCII_TO_LOWER(*p1_str_next);
1087  cmp_val = (CPU_INT16S)char1; /* ... rtn pos p1_str_next val (see Note #3a2B2). */
1088  }
1089  }
1090 
1091 
1092  return (cmp_val);
1093 }
1094 
1095 
1096 /*$PAGE*/
1097 /*
1098 *********************************************************************************************************
1099 * Str_Char()
1100 *
1101 * Description : Search string for first occurrence of specific character.
1102 *
1103 * Argument(s) : pstr Pointer to string (see Note #1).
1104 *
1105 * srch_char Search character.
1106 *
1107 * Return(s) : Pointer to first occurrence of search character in string, if any.
1108 *
1109 * Pointer to NULL, otherwise.
1110 *
1111 * Caller(s) : Application.
1112 *
1113 * Note(s) : (1) String buffer NOT modified.
1114 *
1115 * (2) String search terminates when :
1116 *
1117 * (a) String pointer passed a NULL pointer.
1118 * (1) No string search performed; NULL pointer returned.
1119 *
1120 * (b) String pointer points to NULL.
1121 * (1) String overlaps with NULL address.
1122 * (2) String searched up to but NOT beyond or including the NULL address.
1123 *
1124 * (c) String's terminating NULL character found.
1125 * (1) Search character NOT found in search string; NULL pointer returned.
1126 * (2) Applicable ONLY IF search character is NOT the terminating NULL character.
1127 *
1128 * (d) Search character found.
1129 * (1) Return pointer to first occurrence of search character in search string.
1130 *********************************************************************************************************
1131 */
1132 
1134  CPU_CHAR srch_char)
1135 {
1136  pstr = Str_Char_N((CPU_CHAR *)pstr,
1138  (CPU_CHAR )srch_char);
1139 
1140  return (pstr);
1141 }
1142 
1143 
1144 /*$PAGE*/
1145 /*
1146 *********************************************************************************************************
1147 * Str_Char_N()
1148 *
1149 * Description : Search string for first occurrence of specific character, up to a maximum number of characters.
1150 *
1151 * Argument(s) : pstr Pointer to string (see Note #1).
1152 *
1153 * len_max Maximum number of characters to search (see Notes #2e & #3).
1154 *
1155 * srch_char Search character.
1156 *
1157 * Return(s) : Pointer to first occurrence of search character in string, if any.
1158 *
1159 * Pointer to NULL, otherwise.
1160 *
1161 * Caller(s) : Application.
1162 *
1163 * Note(s) : (1) String buffer NOT modified.
1164 *
1165 * (2) String search terminates when :
1166 *
1167 * (a) String pointer passed a NULL pointer.
1168 * (1) No string search performed; NULL pointer returned.
1169 *
1170 * (b) String pointer points to NULL.
1171 * (1) String overlaps with NULL address.
1172 * (2) String searched up to but NOT beyond or including the NULL address.
1173 *
1174 * (c) String's terminating NULL character found.
1175 * (1) Search character NOT found in search string; NULL pointer returned.
1176 * (2) Applicable ONLY IF search character is NOT the terminating NULL character.
1177 *
1178 * (d) Search character found.
1179 * (1) Return pointer to first occurrence of search character in search string.
1180 *
1181 * (e) 'len_max' number of characters searched.
1182 * (1) 'len_max' number of characters does NOT include terminating NULL character.
1183 *
1184 * (3) Ideally, the 'len_max' parameter would be the last parameter in this function's
1185 * paramter list for consistency with all other custom string library functions.
1186 * However, the 'len_max' parameter is ordered to comply with the standard library
1187 * function's parameter list.
1188 *********************************************************************************************************
1189 */
1190 
1192  CPU_SIZE_T len_max,
1193  CPU_CHAR srch_char)
1194 {
1195  CPU_CHAR *pstr_next;
1196  CPU_SIZE_T len_srch;
1197 
1198 
1199  if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #2a). */
1200  return ((CPU_CHAR *)0);
1201  }
1202 
1203  if (len_max == (CPU_SIZE_T)0) { /* Rtn NULL if srch len equals zero (see Note #2e). */
1204  return ((CPU_CHAR *)0);
1205  }
1206 
1207 
1208  pstr_next = pstr;
1209  pstr_next++;
1210  len_srch = 0;
1211  while (( pstr_next != (CPU_CHAR *) 0 ) && /* Srch str until NULL ptr(s) [see Note #2b] ... */
1212  (*pstr != (CPU_CHAR )'\0') && /* ... or NULL char (see Note #2c) ... */
1213  (*pstr != (CPU_CHAR )srch_char) && /* ... or srch char found (see Note #2d); ... */
1214  ( len_srch < (CPU_SIZE_T)len_max)) { /* ... or max nbr chars srch'd (see Note #2e). */
1215  pstr++;
1216  pstr_next++;
1217  len_srch++;
1218  }
1219 
1220 
1221  if (*pstr != srch_char) { /* If srch char NOT found, str points to NULL; ... */
1222  return ((CPU_CHAR *)0); /* ... rtn NULL (see Notes #2b & #2c). */
1223  }
1224 
1225  return (pstr); /* Else rtn ptr to found srch char (see Note #2d). */
1226 }
1227 
1228 
1229 /*$PAGE*/
1230 /*
1231 *********************************************************************************************************
1232 * Str_Char_Last()
1233 *
1234 * Description : Search string for last occurrence of specific character.
1235 *
1236 * Argument(s) : pstr Pointer to string (see Note #1).
1237 *
1238 * srch_char Search character.
1239 *
1240 * Return(s) : Pointer to last occurrence of search character in string, if any.
1241 *
1242 * Pointer to NULL, otherwise.
1243 *
1244 * Caller(s) : Application.
1245 *
1246 * Note(s) : (1) String buffer NOT modified.
1247 *
1248 * (2) String search terminates when :
1249 *
1250 * (a) String pointer passed a NULL pointer.
1251 * (1) No string search performed; NULL pointer returned.
1252 *
1253 * (b) String pointer points to NULL.
1254 * (1) String overlaps with NULL address.
1255 * (2) String searched up to but NOT beyond or including the NULL address.
1256 * (3) NULL address boundary handled in Str_Len().
1257 *
1258 * (c) String searched from end to beginning.
1259 * (1) Search character NOT found in search string; NULL pointer returned.
1260 * (2) Applicable ONLY IF search character is NOT the terminating NULL character.
1261 *
1262 * (d) Search character found.
1263 * (1) Return pointer to first occurrence of search character in search string.
1264 *********************************************************************************************************
1265 */
1266 
1268  CPU_CHAR srch_char)
1269 {
1270  CPU_CHAR *pstr_next;
1271  CPU_SIZE_T str_len;
1272 
1273 
1274  if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #2a). */
1275  return ((CPU_CHAR *)0);
1276  }
1277 
1278 
1279  pstr_next = pstr;
1280  str_len = Str_Len(pstr);
1281  pstr_next += str_len;
1282  while (( pstr_next != pstr) && /* Srch str from end until begining (see Note #2c) ... */
1283  (*pstr_next != srch_char)) { /* ... until srch char found (see Note #2d). */
1284  pstr_next--;
1285  }
1286 
1287 
1288  if (*pstr_next != srch_char) { /* If srch char NOT found, str points to NULL; ... */
1289  return ((CPU_CHAR *)0); /* ... rtn NULL (see Notes #2b & #2c). */
1290  }
1291 
1292  return (pstr_next); /* Else rtn ptr to found srch char (see Note #2d). */
1293 }
1294 
1295 
1296 /*$PAGE*/
1297 /*
1298 *********************************************************************************************************
1299 * Str_Str()
1300 *
1301 * Description : Search string for first occurence of a specific search string.
1302 *
1303 * Argument(s) : pstr Pointer to string (see Note #1).
1304 *
1305 * psrch_str Pointer to search string (see Note #1).
1306 *
1307 * Return(s) : Pointer to first occurrence of search string in string, if any.
1308 *
1309 * Pointer to NULL, otherwise.
1310 *
1311 * Caller(s) : Application.
1312 *
1313 * Note(s) : (1) String buffers NOT modified.
1314 *
1315 * (2) String search terminates when :
1316 *
1317 * (a) String pointer passed a NULL pointer.
1318 * (1) No string search performed; NULL pointer returned.
1319 *
1320 * (b) Search string length greater than string length.
1321 * (1) No string search performed; NULL pointer returned.
1322 *
1323 * (c) Search string length equal to zero.
1324 * (1) NULL search string at end of string returned.
1325 *
1326 * (d) Entire string has been searched.
1327 * (1) Maximum size of the search is defined as the subtraction of the
1328 * search string length from the string length.
1329 * (2) Search string not found; NULL pointer returned.
1330 *
1331 * (e) Search string found.
1332 * (1) Search string found according to Str_Cmp_N() return value.
1333 * (2) Return pointer to first occurrence of search string in string.
1334 *********************************************************************************************************
1335 */
1336 
1338  CPU_CHAR *psrch_str)
1339 {
1340  CPU_SIZE_T str_len;
1341  CPU_SIZE_T srch_str_len;
1342  CPU_SIZE_T srch_len;
1343  CPU_SIZE_T srch_ix;
1344  CPU_BOOLEAN srch_done;
1345  CPU_INT16S srch_cmp;
1346  CPU_CHAR *pstr_srch_ix;
1347 
1348  /* Rtn NULL if str ptr(s) NULL (see Note #2a). */
1349  if (pstr == (CPU_CHAR *)0) {
1350  return ((CPU_CHAR *)0);
1351  }
1352  if (psrch_str == (CPU_CHAR *)0) {
1353  return ((CPU_CHAR *)0);
1354  }
1355 
1356 
1357  str_len = Str_Len(pstr);
1358  srch_str_len = Str_Len(psrch_str);
1359  if (srch_str_len > str_len) { /* If srch str len > str len, rtn NULL (see Note #2b). */
1360  return ((CPU_CHAR *)0);
1361  }
1362  if (srch_str_len == 0) { /* If srch str len = 0, srch str equal NULL str; ... */
1363  pstr_srch_ix = (CPU_CHAR *)(pstr + str_len); /* ... rtn ptr to NULL str found in str (see Note #2c). */
1364  return (pstr_srch_ix);
1365  }
1366 
1367  srch_len = str_len - srch_str_len; /* Determine srch len (see Note #2d1). */
1368  srch_ix = 0;
1369  srch_done = DEF_NO;
1370  do {
1371  pstr_srch_ix = (CPU_CHAR *)(pstr + srch_ix);
1372  srch_cmp = Str_Cmp_N(pstr_srch_ix, psrch_str, srch_str_len);
1373  srch_done = (srch_cmp == 0) ? DEF_YES : DEF_NO;
1374  srch_ix++;
1375  } while ((srch_done == DEF_NO) && (srch_ix <= srch_len));
1376 
1377 
1378  if (srch_cmp != 0) { /* If srch str NOT found, rtn NULL (see Note #2d). */
1379  return ((CPU_CHAR *)0);
1380  }
1381 
1382  return (pstr_srch_ix); /* Rtn ptr to srch str found in str (see Note #2e). */
1383 }
1384 
1385 
1386 /*$PAGE*/
1387 /*
1388 *********************************************************************************************************
1389 * Str_FmtNbr_Int32U()
1390 *
1391 * Description : Format 32-bit unsigned integer into a multi-digit character string.
1392 *
1393 * Argument(s) : nbr Number to format.
1394 *
1395 * nbr_dig Number of digits to format (see Note #1).
1396 *
1397 * The following may be used to specify the number of digits to format :
1398 *
1399 * DEF_INT_32U_NBR_DIG_MIN Minimum number of 32-bit unsigned digits
1400 * DEF_INT_32U_NBR_DIG_MAX Maximum number of 32-bit unsigned digits
1401 *
1402 * nbr_base Base of number to format (see Note #2).
1403 *
1404 * The following may be used to specify the number base :
1405 *
1406 * DEF_NBR_BASE_BIN Base 2
1407 * DEF_NBR_BASE_OCT Base 8
1408 * DEF_NBR_BASE_DEC Base 10
1409 * DEF_NBR_BASE_HEX Base 16
1410 *
1411 * lead_char Prepend leading character (see Note #3) :
1412 *
1413 * '\0' Do NOT prepend leading character to string.
1414 * Printable character Prepend leading character to string.
1415 * Unprintable character Do NOT format string.
1416 *
1417 * lower_case Format alphabetic characters (if any) in lower case :
1418 *
1419 * DEF_NO Format alphabetic characters in upper case.
1420 * DEF_YES Format alphabetic characters in lower case.
1421 *
1422 * nul Append terminating NULL-character (see Note #4) :
1423 *
1424 * DEF_NO Do NOT append terminating NULL-character to string.
1425 * DEF_YES Append terminating NULL-character to string.
1426 *
1427 * pstr Pointer to character array to return formatted number string (see Note #5).
1428 *
1429 * Return(s) : Pointer to formatted string, if NO errors.
1430 *
1431 * Pointer to NULL, otherwise.
1432 *
1433 * Caller(s) : Application.
1434 *
1435 * Note(s) : (1) If the number of digits to format ('nbr_dig') is less than the number of significant
1436 * integer digits of the number to format ('nbr'); then the most-significant digits of
1437 * the formatted number will be truncated.
1438 *
1439 * Example :
1440 *
1441 * nbr = 23456
1442 * nbr_dig = 3
1443 *
1444 * pstr = "456"
1445 *$PAGE*
1446 * (2) The number's base MUST be between 2 & 36, inclusive.
1447 *
1448 * (3) (a) Leading character option prepends leading characters prior to the first non-zero
1449 * digit. The number of leading characters is such that the total number of integer
1450 * digits is equal to the requested number of integer digits to format ('nbr_dig').
1451 *
1452 * (b) Leading character MUST be a printable ASCII character.
1453 *
1454 * (c) (1) If the value of the number to format is zero ...
1455 * (2) ... & the number of digits to format is non-zero, ...
1456 * (3) ... but NO leading character available; ...
1457 * (4) ... then one digit of '0' value is formatted.
1458 *
1459 * This is NOT a leading character; but a single integer digit of '0' value.
1460 *
1461 * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
1462 * array formatting.
1463 *
1464 * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
1465 * terminate option DISABLED will cause character string run-on.
1466 *
1467 * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
1468 *
1469 * (b) To prevent character buffer overrun :
1470 *
1471 * Character array size MUST be >= ('nbr_dig' +
1472 * 1 'NUL' terminator) characters
1473 *********************************************************************************************************
1474 */
1475 
1477  CPU_INT08U nbr_dig,
1478  CPU_INT08U nbr_base,
1479  CPU_CHAR lead_char,
1480  CPU_BOOLEAN lower_case,
1481  CPU_BOOLEAN nul,
1482  CPU_CHAR *pstr)
1483 {
1484  CPU_CHAR *pstr_fmt;
1485 
1486 
1487  pstr_fmt = Str_FmtNbr_Int32((CPU_INT32U )nbr, /* Fmt unsigned int into str. */
1488  (CPU_INT08U )nbr_dig,
1489  (CPU_INT08U )nbr_base,
1491  (CPU_CHAR )lead_char,
1492  (CPU_BOOLEAN)lower_case,
1493  (CPU_BOOLEAN)nul,
1494  (CPU_CHAR *)pstr);
1495 
1496  return (pstr_fmt);
1497 }
1498 
1499 
1500 /*$PAGE*/
1501 /*
1502 *********************************************************************************************************
1503 * Str_FmtNbr_Int32S()
1504 *
1505 * Description : Format 32-bit signed integer into a multi-digit character string.
1506 *
1507 * Argument(s) : nbr Number to format.
1508 *
1509 * nbr_dig Number of digits to format (see Note #1).
1510 *
1511 * The following may be used to specify the number of digits to format :
1512 *
1513 * DEF_INT_32S_NBR_DIG_MIN Minimum number of 32-bit signed digits
1514 * DEF_INT_32S_NBR_DIG_MAX Maximum number of 32-bit signed digits
1515 *
1516 * nbr_base Base of number to format (see Note #2).
1517 *
1518 * The following may be used to specify the number base :
1519 *
1520 * DEF_NBR_BASE_BIN Base 2
1521 * DEF_NBR_BASE_OCT Base 8
1522 * DEF_NBR_BASE_DEC Base 10
1523 * DEF_NBR_BASE_HEX Base 16
1524 *
1525 * lead_char Prepend leading character (see Note #3) :
1526 *
1527 * '\0' Do NOT prepend leading character to string.
1528 * Printable character Prepend leading character to string.
1529 * Unprintable character Do NOT format string.
1530 *
1531 * lower_case Format alphabetic characters (if any) in lower case :
1532 *
1533 * DEF_NO Format alphabetic characters in upper case.
1534 * DEF_YES Format alphabetic characters in lower case.
1535 *
1536 * nul Append terminating NULL-character (see Note #4) :
1537 *
1538 * DEF_NO Do NOT append terminating NULL-character to string.
1539 * DEF_YES Append terminating NULL-character to string.
1540 *
1541 * pstr Pointer to character array to return formatted number string (see Note #5).
1542 *
1543 * Return(s) : Pointer to formatted string, if NO errors.
1544 *
1545 * Pointer to NULL, otherwise.
1546 *
1547 * Caller(s) : Application.
1548 *
1549 * Note(s) : (1) (a) If the number of digits to format ('nbr_dig') is less than the number of significant
1550 * integer digits of the number to format ('nbr'); then the most-significant digits of
1551 * the formatted number will be truncated.
1552 *
1553 * Example :
1554 *
1555 * nbr = 23456
1556 * nbr_dig = 3
1557 *
1558 * pstr = "456"
1559 *
1560 * (b) If number to format ('nbr') is negative but the most-significant digits of the
1561 * formatted number are truncated (see Note #2a); the negative sign still prefixes
1562 * the truncated formatted number.
1563 *
1564 * Example :
1565 *
1566 * nbr = -23456
1567 * nbr_dig = 3
1568 *
1569 * pstr = "-456"
1570 *$PAGE*
1571 * (2) The number's base MUST be between 2 & 36, inclusive.
1572 *
1573 * (3) (a) Leading character option prepends leading characters prior to the first non-zero
1574 * digit. The number of leading characters is such that the total number of integer
1575 * digits is equal to the requested number of integer digits to format ('nbr_dig').
1576 *
1577 * (b) Leading character MUST be a printable ASCII character.
1578 *
1579 * (c) (1) If the value of the number to format is zero ...
1580 * (2) ... & the number of digits to format is non-zero, ...
1581 * (3) ... but NO leading character available; ...
1582 * (4) ... then one digit of '0' value is formatted.
1583 *
1584 * This is NOT a leading character; but a single integer digit of '0' value.
1585 *
1586 * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
1587 * array formatting.
1588 *
1589 * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
1590 * terminate option DISABLED will cause character string run-on.
1591 *
1592 * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
1593 *
1594 * (b) To prevent character buffer overrun :
1595 *
1596 * Character array size MUST be >= ('nbr_dig' +
1597 * 1 negative sign +
1598 * 1 'NUL' terminator) characters
1599 *********************************************************************************************************
1600 */
1601 
1603  CPU_INT08U nbr_dig,
1604  CPU_INT08U nbr_base,
1605  CPU_CHAR lead_char,
1606  CPU_BOOLEAN lower_case,
1607  CPU_BOOLEAN nul,
1608  CPU_CHAR *pstr)
1609 {
1610  CPU_CHAR *pstr_fmt;
1611  CPU_INT32S nbr_fmt;
1612  CPU_BOOLEAN nbr_neg;
1613 
1614 
1615  nbr_fmt = nbr;
1616  if (nbr_fmt < 0) { /* If nbr neg, ... */
1617  nbr_fmt = -nbr_fmt; /* ... negate nbr. */
1618  nbr_neg = DEF_YES;
1619  } else {
1620  nbr_neg = DEF_NO;
1621  }
1622 
1623  pstr_fmt = Str_FmtNbr_Int32((CPU_INT32U )nbr_fmt, /* Fmt signed int into str. */
1624  (CPU_INT08U )nbr_dig,
1625  (CPU_INT08U )nbr_base,
1626  (CPU_BOOLEAN)nbr_neg,
1627  (CPU_CHAR )lead_char,
1628  (CPU_BOOLEAN)lower_case,
1629  (CPU_BOOLEAN)nul,
1630  (CPU_CHAR *)pstr);
1631 
1632  return (pstr_fmt);
1633 }
1634 
1635 
1636 /*$PAGE*/
1637 /*
1638 *********************************************************************************************************
1639 * Str_FmtNbr_32()
1640 *
1641 * Description : Format number into a multi-digit character string.
1642 *
1643 * Argument(s) : nbr Number to format (see Note #1).
1644 *
1645 * nbr_dig Number of decimal digits to format (see Note #2).
1646 *
1647 * nbr_dp Number of decimal point digits to format.
1648 *
1649 * lead_char Prepend leading character (see Note #3) :
1650 *
1651 * '\0' Do NOT prepend leading character to string.
1652 * Printable character Prepend leading character to string.
1653 * Unprintable character Do NOT format string (see Note #6b).
1654 *
1655 * nul Append terminating NULL-character (see Note #4) :
1656 *
1657 * DEF_NO Do NOT append terminating NULL-character to string.
1658 * DEF_YES Append terminating NULL-character to string.
1659 *
1660 * pstr Pointer to character array to return formatted number string (see Note #5).
1661 *
1662 * Return(s) : Pointer to formatted string, if NO errors (see Note #6).
1663 *
1664 * Pointer to NULL, otherwise.
1665 *
1666 * Caller(s) : Application.
1667 *
1668 * Note(s) : (1) (a) The maximum accuracy for 32-bit floating-point numbers :
1669 *
1670 *
1671 * Maximum Accuracy log [Internal-Base ^ (Number-Internal-Base-Digits)]
1672 * 32-bit Floating-point Number = -----------------------------------------------------
1673 * log [External-Base]
1674 *
1675 * log [2 ^ 24]
1676 * = --------------
1677 * log [10]
1678 *
1679 * < 7.225 Base-10 Digits
1680 *
1681 * where
1682 * Internal-Base Internal number base of floating-
1683 * point numbers (i.e. 2)
1684 * External-Base External number base of floating-
1685 * point numbers (i.e. 10)
1686 * Number-Internal-Base-Digits Number of internal number base
1687 * significant digits (i.e. 24)
1688 *
1689 * (b) Some compilers' floating-point routines MAY further reduce the maximum accuracy.
1690 *
1691 * (c) If the total number of digits to format ('nbr_dig + nbr_dp') is greater than the
1692 * maximum accuracy; digits following the first, significantly-accurate digits will
1693 * be inaccurate.
1694 *$PAGE*
1695 * (2) (a) If the number of digits to format ('nbr_dig') is less than the number of significant
1696 * integer digits of the number to format ('nbr'); then the most-significant digits of
1697 * the formatted number will be truncated.
1698 *
1699 * Example :
1700 *
1701 * nbr = 23456.789
1702 * nbr_dig = 3
1703 * nbr_dp = 2
1704 *
1705 * pstr = "456.78"
1706 *
1707 * (b) If number to format ('nbr') is negative but the most-significant digits of the
1708 * formatted number are truncated (see Note #2a); the negative sign still prefixes
1709 * the truncated formatted number.
1710 *
1711 * Example :
1712 *
1713 * nbr = -23456.789
1714 * nbr_dig = 3
1715 * nbr_dp = 2
1716 *
1717 * pstr = "-456.78"
1718 *
1719 * (3) (a) Leading character option prepends leading characters prior to the first non-zero
1720 * digit. The number of leading characters is such that the total number of integer
1721 * digits is equal to the requested number of integer digits to format ('nbr_dig').
1722 *
1723 * (b) Leading character MUST be a printable ASCII character.
1724 *
1725 * (c) (1) If the integer value of the number to format is zero ...
1726 * (2) ... & the number of digits to format is non-zero, ...
1727 * (3) ... but NO leading character available; ...
1728 * (4) ... then one digit of '0' value is formatted.
1729 *
1730 * This is NOT a leading character; but a single integer digit of '0' value.
1731 *
1732 * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
1733 * array formatting.
1734 *
1735 * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
1736 * terminate option DISABLED will cause character string run-on.
1737 *
1738 * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
1739 *
1740 * (b) To prevent character buffer overrun :
1741 *
1742 * Character array size MUST be >= ('nbr_dig' +
1743 * 'nbr_dp' +
1744 * 1 negative sign +
1745 * 1 decimal point +
1746 * 1 'NUL' terminator) characters
1747 *
1748 * (6) String format terminates when :
1749 *
1750 * (a) Format string pointer is passed a NULL pointer.
1751 * (1) No string format performed; NULL pointer returned.
1752 *
1753 * (b) Lead character is NOT a printable character (see Note #3b).
1754 * (1) No string format performed; NULL pointer returned.
1755 *
1756 * (c) Number successfully formatted into character string array.
1757 *********************************************************************************************************
1758 */
1759 /*$PAGE*/
1760 #if (LIB_STR_CFG_FP_EN == DEF_ENABLED)
1761 CPU_CHAR *Str_FmtNbr_32 (CPU_FP32 nbr,
1762  CPU_INT08U nbr_dig,
1763  CPU_INT08U nbr_dp,
1764  CPU_CHAR lead_char,
1765  CPU_BOOLEAN nul,
1766  CPU_CHAR *pstr)
1767 {
1768  CPU_CHAR *pstr_fmt;
1769  CPU_FP32 nbr_fmt;
1770  CPU_INT32U dig_nbr;
1771  CPU_INT32U dig_val;
1772  CPU_FP32 dig_exp;
1773  CPU_FP32 dp_exp;
1774  CPU_INT08U i;
1775  CPU_BOOLEAN print_char;
1776 
1777 
1778  if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if str ptr NULL (see Note #6a). */
1779  return ((CPU_CHAR *)0);
1780  }
1781 
1782  if (lead_char != (CPU_CHAR)'\0') {
1783  print_char = ASCII_IsPrint(lead_char);
1784  if (print_char != DEF_YES) { /* Rtn NULL if lead char non-printable (see Note #6b). */
1785  return ((CPU_CHAR *)0);
1786  }
1787  }
1788 
1789 
1790  nbr_fmt = nbr;
1791  pstr_fmt = pstr;
1792 
1793  if (nbr_fmt < 0.0f) { /* If nbr neg, ... */
1794  nbr_fmt = -nbr_fmt; /* ... negate nbr; ... */
1795  if ((nbr_dig > 0) || /* ... & if at least one dig ... */
1796  (nbr_dp > 0)) { /* ... or at least one dp; ... */
1797  *pstr_fmt++ = '-'; /* ... prepend a neg sign (see Note #2b). */
1798  }
1799  }
1800 
1801  if (nbr_dig > 0) {
1802  dig_exp = 1.0f;
1803  for (i = 1; i < nbr_dig; i++) {
1804  dig_exp *= 10.0f;
1805  }
1806  for (i = nbr_dig; i > 0; i--) { /* Fmt str for desired nbr digs. */
1807  dig_nbr = (CPU_INT32U)(nbr_fmt / dig_exp);
1808  if ((dig_nbr > 0) || /* If dig nbr > 0 (see Note #3c1), ... */
1809  (nbr_dig == 1) || /* ... OR exactly 1 dig to fmt (see Note #3c2), ... */
1810  (i == 1)) { /* ... OR on one's dig to fmt; ... */
1811  /* ... calc & fmt dig val. */
1812  dig_val = (CPU_INT32U)(dig_nbr % 10 );
1813  *pstr_fmt++ = (CPU_CHAR )(dig_val + '0');
1814 
1815  } else if (lead_char != (CPU_CHAR)'\0') { /* ... else if avail, ... */
1816  *pstr_fmt++ = (CPU_CHAR)lead_char; /* ... fmt lead char. */
1817  }
1818 
1819  dig_exp /= 10.0f; /* Shift to next least-significant dig. */
1820  }
1821  }
1822 
1823  if (nbr_dp > 0) {
1824  *pstr_fmt++ = '.'; /* Append dp prior to dp conversion. */
1825  dp_exp = 10.0f;
1826  for (i = 0; i < nbr_dp; i++) { /* Fmt str for desired nbr dp. */
1827  dig_nbr = (CPU_INT32U)(nbr_fmt * dp_exp);
1828  dig_val = (CPU_INT32U)(dig_nbr % 10 );
1829  *pstr_fmt++ = (CPU_CHAR )(dig_val + '0');
1830  dp_exp *= 10.0f; /* Shift to next least-significant dp. */
1831  }
1832  }
1833 
1834  if (nul != DEF_NO) { /* If NOT DISABLED, append NULL char (see Note #4). */
1835  *pstr_fmt = (CPU_CHAR)'\0';
1836  }
1837 
1838 
1839  return (pstr); /* Rtn ptr to fmt'd str (see Note #6c). */
1840 }
1841 #endif
1842 
1843 
1844 /*$PAGE*/
1845 /*
1846 *********************************************************************************************************
1847 * Str_ParseNbr_Int32U()
1848 *
1849 * Description : Parse 32-bit unsigned integer from string.
1850 *
1851 * Argument(s) : pstr Pointer to string (see Notes #1 & #2a).
1852 *
1853 * pstr_next Pointer to a variable to ... :
1854 *
1855 * (a) Return a pointer to first character following the integer string,
1856 * if NO errors (see Note #2a2B2);
1857 * (b) Return a pointer to 'pstr',
1858 * otherwise (see Note #2a2A2).
1859 *
1860 * nbr_base Base of number to parse (see Notes #2a1B1 & #2a2B1).
1861 *
1862 * Return(s) : Parsed integer, if integer parsed with NO overflow (see Note #2a3A).
1863 *
1864 * DEF_INT_32U_MAX_VAL, if integer parsed but overflowed (see Note #2a3A1).
1865 *
1866 * 0, otherwise (see Note #2a3B).
1867 *
1868 * Caller(s) : Application.
1869 *
1870 * Note(s) : (1) String buffer NOT modified.
1871 *
1872 * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : DESCRIPTION' states that "these
1873 * functions shall convert the initial portion of the string pointed to by 'str' to a
1874 * type unsigned long ... representation" :
1875 *
1876 * (1) "First, they decompose the input string into three parts" :
1877 *
1878 * (A) "An initial, possibly empty, sequence of white-space characters [as specified
1879 * by isspace()]."
1880 *
1881 * (1) "The subject sequence is defined as the longest initial subsequence of the
1882 * input string, starting with the first non-white-space character that is of
1883 * the expected form. The subject sequence shall contain no characters if the
1884 * input string is empty or consists entirely of white-space characters."
1885 *
1886 * (B) (1) "A subject sequence interpreted as an integer represented in some radix
1887 * determined by the value of 'base'" :
1888 *
1889 * (a) "If the value of 'base' is 0, the expected form of the subject sequence
1890 * is that of a decimal constant, octal constant, or hexadecimal constant" :
1891 *
1892 * (1) "A decimal constant begins with a non-zero digit, and consists of a
1893 * sequence of decimal digits."
1894 *
1895 * (2) "An octal constant consists of the prefix '0' optionally followed by
1896 * a sequence of the digits '0' to '7' only."
1897 *
1898 * (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
1899 * by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
1900 * (or 'F') with values 10 to 15 respectively."
1901 *
1902 * (b) "If the value of 'base' is between 2 and 36, the expected form of the
1903 * subject sequence is a sequence of letters and digits representing an
1904 * integer with the radix specified by 'base'" :
1905 *
1906 * (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
1907 * ascribed the values 10 to 35"; ...
1908 * (B) "only letters whose ascribed values are less than that of base
1909 * are permitted."
1910 *
1911 * (2) (A) "If the value of 'base' is 16, the characters '0x' or '0X' may
1912 * optionally precede the sequence of letters and digits."
1913 *
1914 * (B) Although NO specification states that "if the value of 'base'
1915 * is" 8, the '0' character "may optionally precede the sequence
1916 * of letters and digits"; it seems reasonable to allow the '0'
1917 * character to be optionally parsed.
1918 *
1919 * (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
1920 *
1921 * (a) However, it does NOT seem reasonable to parse & convert a negative number
1922 * integer string into an unsigned integer.
1923 *
1924 * (C) (1) (a) "A final string of one or more unrecognized characters," ...
1925 * (b) "including the terminating null byte of the input string" ...
1926 * (2) "other than a sign or a permissible letter or digit."
1927 *$PAGE*
1928 * (2) Second, "they shall attempt to convert the subject sequence to an unsigned integer" :
1929 *
1930 * (A) "If the subject sequence is empty or does not have the expected form" :
1931 *
1932 * (1) "no conversion [is] performed"; ...
1933 * (2) "the value of 'str' [is] stored in the object pointed to by 'endptr',
1934 * provided that 'endptr' is not a null pointer."
1935 *
1936 * (B) "If the subject sequence has the expected form" :
1937 *
1938 * (1) (a) "and the value of 'base' is 0, the sequence of characters starting with
1939 * the first digit shall be interpreted as an integer constant."
1940 *
1941 * (b) "and the value of 'base' is between 2 and 36, it shall be used as the
1942 * base for conversion, ascribing to each letter its value as given above"
1943 * (see Note #2a1B1b1A).
1944 *
1945 * (2) "A pointer to the final string shall be stored in the object pointed to by
1946 * 'endptr', provided that 'endptr' is not a null pointer."
1947 *
1948 * (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : RETURN VALUE' states that :
1949 *
1950 * (A) "Upon successful completion, these functions shall return the converted value."
1951 * (1) "If the correct value is outside the range of representable values, {ULONG_MAX}
1952 * ... shall be returned."
1953 *
1954 * (B) "If no conversion could be performed, 0 shall be returned."
1955 *
1956 * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
1957 * shall fail if" :
1958 *
1959 * (A) "[EINVAL] - The value of 'base' is not supported."
1960 *
1961 * (B) "[ERANGE] - The value to be returned is not representable."
1962 *
1963 * (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
1964 * may fail if" :
1965 *
1966 * (A) "[EINVAL] - No conversion could be performed."
1967 *
1968 * (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
1969 *
1970 * (a) Valid parse string integer :
1971 *
1972 * pstr = " ABCDE xyz"
1973 * nbr_base = 16
1974 *
1975 * nbr = 703710
1976 * pstr_next = " xyz"
1977 *
1978 *
1979 * (b) Invalid parse string integer :
1980 *
1981 * pstr = " ABCDE"
1982 * nbr_base = 10
1983 *
1984 * nbr = 0
1985 * pstr_next = pstr = " ABCDE"
1986 *
1987 *
1988 * (c) Valid hexadecimal parse string integer :
1989 *
1990 * pstr = " 0xGABCDE"
1991 * nbr_base = 16
1992 *
1993 * nbr = 0
1994 * pstr_next = "xGABCDE"
1995 *
1996 *
1997 * (d) Valid decimal parse string integer ('0x' prefix ignored
1998 * following invalid hexadecimal characters) :
1999 *
2000 * pstr = " 0xGABCDE"
2001 * nbr_base = 0
2002 *
2003 * nbr = 0
2004 * pstr_next = "xGABCDE"
2005 *
2006 *
2007 * (e) Valid decimal parse string integer ('0' prefix ignored
2008 * following invalid octal characters) :
2009 *
2010 * pstr = " 0GABCDE"
2011 * nbr_base = 0
2012 *
2013 * nbr = 0
2014 * pstr_next = "GABCDE"
2015 *
2016 *$PAGE*
2017 * (f) Parse string integer overflow :
2018 *
2019 * pstr = " 12345678901234567890*123456"
2020 * nbr_base = 10
2021 *
2022 * nbr = DEF_INT_32U_MAX_VAL
2023 * pstr_next = "*123456"
2024 *
2025 *
2026 * (g) Invalid negative unsigned parse string :
2027 *
2028 * pstr = " -12345678901234567890*123456"
2029 * nbr_base = 10
2030 *
2031 * nbr = 0
2032 * pstr_next = pstr = " -12345678901234567890*123456"
2033 *
2034 *********************************************************************************************************
2035 */
2036 
2038  CPU_CHAR **pstr_next,
2039  CPU_INT08U nbr_base)
2040 {
2041  CPU_INT32U nbr;
2042 
2043 
2044  nbr = Str_ParseNbr_Int32((CPU_CHAR *)pstr, /* Parse/convert str ... */
2045  (CPU_CHAR **)pstr_next,
2046  (CPU_INT08U )nbr_base,
2047  (CPU_BOOLEAN )DEF_NO, /* ... as unsigned int (see Note #2a2). */
2048  (CPU_BOOLEAN *)0);
2049 
2050  return (nbr);
2051 }
2052 
2053 
2054 /*$PAGE*/
2055 /*
2056 *********************************************************************************************************
2057 * Str_ParseNbr_Int32S()
2058 *
2059 * Description : Parse 32-bit signed integer from string.
2060 *
2061 * Argument(s) : pstr Pointer to string (see Notes #1 & #2a).
2062 *
2063 * pstr_next Pointer to a variable to ... :
2064 *
2065 * (a) Return a pointer to first character following the integer string,
2066 * if NO errors (see Note #2a2B2);
2067 * (b) Return a pointer to 'pstr',
2068 * otherwise (see Note #2a2A2).
2069 *
2070 * nbr_base Base of number to parse (see Notes #2a1B1 & #2a2B1).
2071 *
2072 * Return(s) : Parsed integer, if integer parsed with NO over- or underflow (see Note #2a3A).
2073 *
2074 * DEF_INT_32S_MIN_VAL, if integer parsed but negatively underflowed (see Note #2a3A1a).
2075 *
2076 * DEF_INT_32U_MAX_VAL, if integer parsed but positively overflowed (see Note #2a3A1b).
2077 *
2078 * 0, otherwise (see Note #2a3B).
2079 *
2080 * Caller(s) : Application.
2081 *
2082 * Note(s) : (1) String buffer NOT modified.
2083 *
2084 * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtol() : DESCRIPTION' states that "these
2085 * functions shall convert the initial portion of the string pointed to by 'str' to a
2086 * type long ... representation" :
2087 *
2088 * (1) "First, they decompose the input string into three parts" :
2089 *
2090 * (A) "An initial, possibly empty, sequence of white-space characters [as specified
2091 * by isspace()]."
2092 *
2093 * (1) "The subject sequence is defined as the longest initial subsequence of the
2094 * input string, starting with the first non-white-space character that is of
2095 * the expected form. The subject sequence shall contain no characters if the
2096 * input string is empty or consists entirely of white-space characters."
2097 *
2098 * (B) (1) "A subject sequence interpreted as an integer represented in some radix
2099 * determined by the value of 'base'" :
2100 *
2101 * (a) "If the value of 'base' is 0, the expected form of the subject sequence
2102 * is that of a decimal constant, octal constant, or hexadecimal constant" :
2103 *
2104 * (1) "A decimal constant begins with a non-zero digit, and consists of a
2105 * sequence of decimal digits."
2106 *
2107 * (2) "An octal constant consists of the prefix '0' optionally followed by
2108 * a sequence of the digits '0' to '7' only."
2109 *
2110 * (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
2111 * by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
2112 * (or 'F') with values 10 to 15 respectively."
2113 *
2114 * (b) "If the value of 'base' is between 2 and 36, the expected form of the
2115 * subject sequence is a sequence of letters and digits representing an
2116 * integer with the radix specified by 'base'" :
2117 *
2118 * (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
2119 * ascribed the values 10 to 35"; ...
2120 * (B) "only letters whose ascribed values are less than that of base
2121 * are permitted."
2122 *
2123 * (2) (A) "If the value of 'base' is 16, the characters '0x' or '0X' may
2124 * optionally precede the sequence of letters and digits."
2125 *
2126 * (B) Although NO specification states that "if the value of 'base'
2127 * is" 8, the '0' character "may optionally precede the sequence
2128 * of letters and digits"; it seems reasonable to allow the '0'
2129 * character to be optionally parsed.
2130 *
2131 * (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
2132 *
2133 * (a) However, it does NOT seem reasonable to parse & convert a negative number
2134 * integer string into an unsigned integer.
2135 *
2136 * (C) (1) (a) "A final string of one or more unrecognized characters," ...
2137 * (b) "including the terminating null byte of the input string" ...
2138 * (2) "other than a sign or a permissible letter or digit."
2139 *$PAGE*
2140 * (2) Second, "they shall attempt to convert the subject sequence to an integer" :
2141 *
2142 * (A) "If the subject sequence is empty or does not have the expected form" :
2143 *
2144 * (1) "no conversion is performed"; ...
2145 * (2) "the value of 'str' is stored in the object pointed to by 'endptr',
2146 * provided that 'endptr' is not a null pointer."
2147 *
2148 * (B) "If the subject sequence has the expected form" :
2149 *
2150 * (1) (a) "and the value of 'base' is 0, the sequence of characters starting with
2151 * the first digit shall be interpreted as an integer constant."
2152 *
2153 * (b) "and the value of 'base' is between 2 and 36, it shall be used as the
2154 * base for conversion, ascribing to each letter its value as given above"
2155 * (see Note #2a1B1b1A).
2156 *
2157 * (2) "A pointer to the final string shall be stored in the object pointed to by
2158 * 'endptr', provided that 'endptr' is not a null pointer."
2159 *
2160 * (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtol() : RETURN VALUE' states that :
2161 *
2162 * (A) "Upon successful completion, these functions shall return the converted value."
2163 *
2164 * (1) "If the correct value is outside the range of representable values", either
2165 * of the following "shall be returned" :
2166 * (a) "{LONG_MIN}" or ...
2167 * (b) "{LONG_MAX}"
2168 *
2169 * (B) "If no conversion could be performed, 0 shall be returned."
2170 *
2171 * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
2172 * shall fail if" :
2173 *
2174 * (A) "[EINVAL] - The value of 'base' is not supported."
2175 *
2176 * (B) "[ERANGE] - The value to be returned is not representable."
2177 *
2178 * (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
2179 * may fail if" :
2180 *
2181 * (A) "[EINVAL] - No conversion could be performed."
2182 *
2183 * (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
2184 *
2185 * (a) Valid parse string integer :
2186 *
2187 * pstr = " ABCDE xyz"
2188 * nbr_base = 16
2189 *
2190 * nbr = 703710
2191 * pstr_next = " xyz"
2192 *
2193 *
2194 * (b) Invalid parse string integer :
2195 *
2196 * pstr = " ABCDE"
2197 * nbr_base = 10
2198 *
2199 * nbr = 0
2200 * pstr_next = pstr = " ABCDE"
2201 *
2202 *
2203 * (c) Valid hexadecimal parse string integer :
2204 *
2205 * pstr = " 0xGABCDE"
2206 * nbr_base = 16
2207 *
2208 * nbr = 0
2209 * pstr_next = "xGABCDE"
2210 *
2211 *
2212 * (d) Valid decimal parse string integer ('0x' prefix ignored
2213 * following invalid hexadecimal characters) :
2214 *
2215 * pstr = " 0xGABCDE"
2216 * nbr_base = 0
2217 *
2218 * nbr = 0
2219 * pstr_next = "xGABCDE"
2220 *
2221 *
2222 * (e) Valid decimal parse string integer ('0' prefix ignored
2223 * following invalid octal characters) :
2224 *
2225 * pstr = " 0GABCDE"
2226 * nbr_base = 0
2227 *
2228 * nbr = 0
2229 * pstr_next = "GABCDE"
2230 *
2231 *$PAGE*
2232 * (f) Parse string integer overflow :
2233 *
2234 * pstr = " 12345678901234567890*123456"
2235 * nbr_base = 10
2236 *
2237 * nbr = DEF_INT_32S_MAX_VAL
2238 * pstr_next = "*123456"
2239 *
2240 *
2241 * (g) Parse string integer underflow :
2242 *
2243 * pstr = " -12345678901234567890*123456"
2244 * nbr_base = 10
2245 *
2246 * nbr = DEF_INT_32S_MIN_VAL
2247 * pstr_next = "*123456"
2248 *
2249 *********************************************************************************************************
2250 */
2251 
2253  CPU_CHAR **pstr_next,
2254  CPU_INT08U nbr_base)
2255 {
2256  CPU_INT32S nbr;
2257  CPU_INT32U nbr_abs;
2258  CPU_BOOLEAN nbr_neg;
2259 
2260 
2261  nbr_abs = Str_ParseNbr_Int32((CPU_CHAR *) pstr, /* Parse/convert str ... */
2262  (CPU_CHAR **) pstr_next,
2263  (CPU_INT08U ) nbr_base,
2264  (CPU_BOOLEAN ) DEF_YES, /* ... as signed int (see Note #2a2). */
2265  (CPU_BOOLEAN *)&nbr_neg);
2266 
2267  if (nbr_neg == DEF_NO) { /* Chk for neg nbr & ovf/undf (see Note #2a3A1). */
2269  : (CPU_INT32S)nbr_abs;
2270  } else {
2272  : -(CPU_INT32S)nbr_abs;
2273  }
2274 
2275  return (nbr);
2276 }
2277 
2278 
2279 /*$PAGE*/
2280 /*
2281 *********************************************************************************************************
2282 *********************************************************************************************************
2283 * LOCAL FUNCTIONS
2284 *********************************************************************************************************
2285 *********************************************************************************************************
2286 */
2287 
2288 /*
2289 *********************************************************************************************************
2290 * Str_FmtNbr_Int32()
2291 *
2292 * Description : Format 32-bit integer into a multi-digit character string.
2293 *
2294 * Argument(s) : nbr Number to format.
2295 *
2296 * nbr_dig Number of digits to format (see Note #1).
2297 *
2298 * nbr_base Base of number to format (see Note #2).
2299 *
2300 * nbr_neg Indicates whether number to format is negative :
2301 *
2302 * DEF_NO Number is non-negative.
2303 * DEF_YES Number is negative.
2304 *
2305 * lead_char Prepend leading character (see Note #3) :
2306 *
2307 * '\0' Do NOT prepend leading character to string.
2308 * Printable character Prepend leading character to string.
2309 * Unprintable character Do NOT format string (see Note #6b).
2310 *
2311 * lower_case Format alphabetic characters (if any) in lower case :
2312 *
2313 * DEF_NO Format alphabetic characters in upper case.
2314 * DEF_YES Format alphabetic characters in lower case.
2315 *
2316 * nul Append terminating NULL-character (see Note #4) :
2317 *
2318 * DEF_NO Do NOT append terminating NULL-character to string.
2319 * DEF_YES Append terminating NULL-character to string.
2320 *
2321 * pstr Pointer to character array to return formatted number string (see Note #5).
2322 *
2323 * Return(s) : Pointer to formatted string, if NO errors (see Note #6).
2324 *
2325 * Pointer to NULL, otherwise.
2326 *
2327 * Caller(s) : Str_FmtNbr_Int32U(),
2328 * Str_FmtNbr_Int32S().
2329 *
2330 * Note(s) : (1) (a) The maximum number of digits to format for 32-bit integer numbers :
2331 *
2332 *
2333 * Maximum Number of [ log (Number) ]
2334 * 32-bit Integer Digits = floor [ -------------- + 1 ]
2335 * to Format [ log (Base) ]
2336 *
2337 * where
2338 * Number Number to format
2339 * Base Base of number to format
2340 *
2341 * (b) (1) If the number of digits to format ('nbr_dig') is less than the number of
2342 * significant integer digits of the number to format ('nbr'); then the most-
2343 * significant digits of the formatted number will be truncated.
2344 *
2345 * Example :
2346 *
2347 * nbr = 23456
2348 * nbr_dig = 3
2349 *
2350 * pstr = "456"
2351 *
2352 * (2) If number to format ('nbr') is negative but the most-significant digits of
2353 * the formatted number are truncated (see Note #2a); the negative sign still
2354 * prefixes the truncated formatted number.
2355 *
2356 * Example :
2357 *
2358 * nbr = -23456
2359 * nbr_dig = 3
2360 *
2361 * pstr = "-456"
2362 *$PAGE*
2363 * (2) The number's base MUST be between 2 & 36, inclusive.
2364 *
2365 * (3) (a) Leading character option prepends leading characters prior to the first non-zero
2366 * digit. The number of leading characters is such that the total number of integer
2367 * digits is equal to the requested number of integer digits to format ('nbr_dig').
2368 *
2369 * (b) Leading character MUST be a printable ASCII character.
2370 *
2371 * (c) (1) If the value of the number to format is zero ...
2372 * (2) ... & the number of digits to format is non-zero, ...
2373 * (3) ... but NO leading character available; ...
2374 * (4) ... then one digit of '0' value is formatted.
2375 *
2376 * This is NOT a leading character; but a single integer digit of '0' value.
2377 *
2378 * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character
2379 * array formatting.
2380 *
2381 * (b) WARNING: Unless 'pstr' character array is pre-/post-terminated, NULL-character
2382 * terminate option DISABLED will cause character string run-on.
2383 *
2384 * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller.
2385 *
2386 * (b) To prevent character buffer overrun :
2387 *
2388 * Character array size MUST be >= ('nbr_dig' +
2389 * 1 negative sign +
2390 * 1 'NUL' terminator) characters
2391 * (6) String format terminates when :
2392 *
2393 * (a) Format string pointer is passed a NULL pointer.
2394 * (1) No string format performed; NULL pointer returned.
2395 *
2396 * (b) Base is passed an invalid base (see Note #2).
2397 * (1) No string format performed; NULL pointer returned.
2398 *
2399 * (c) Lead character is NOT a printable character (see Note #3b).
2400 * (1) No string format performed; NULL pointer returned.
2401 *
2402 * (d) Number successfully formatted into character string array.
2403 *********************************************************************************************************
2404 */
2405 
2407  CPU_INT08U nbr_dig,
2408  CPU_INT08U nbr_base,
2409  CPU_BOOLEAN nbr_neg,
2410  CPU_CHAR lead_char,
2411  CPU_BOOLEAN lower_case,
2412  CPU_BOOLEAN nul,
2413  CPU_CHAR *pstr)
2414 {
2415  CPU_CHAR *pstr_fmt;
2416  CPU_INT32U nbr_fmt;
2417  CPU_INT32U nbr_exp;
2418  CPU_INT32U nbr_dig_val;
2419  CPU_INT08U log_floor;
2420  CPU_INT08U i;
2421  CPU_BOOLEAN ovf;
2422  CPU_BOOLEAN print_char;
2423 
2424 
2425 /*$PAGE*/
2426  if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if str ptr NULL (see Note #6a). */
2427  return ((CPU_CHAR *)0);
2428  }
2429  /* Rtn NULL if invalid base (see Note #6b). */
2430  if ((nbr_base < 2) ||
2431  (nbr_base > 36)) {
2432  return ((CPU_CHAR *)0);
2433  }
2434 
2435  if (lead_char == (CPU_CHAR)'\0') { /* If lead char NOT avail, ... */
2436  log_floor = 1; /* ... calc floor of nbr digs (see Note #1a) ... */
2437  nbr_exp = nbr_base;
2438  ovf = DEF_NO;
2439  while ((nbr_exp <= nbr) &&
2440  (ovf == DEF_NO)) {
2441  if (nbr_exp <= Str_MultOvfThTbl_Int32U[nbr_base]) {
2442  nbr_exp *= nbr_base;
2443  } else {
2444  ovf = DEF_YES;
2445  }
2446  log_floor++;
2447  }
2448  if (nbr_dig > log_floor) {
2449  nbr_dig = log_floor; /* ... & lim max nbr digs. */
2450  }
2451 
2452  } else {
2453  print_char = ASCII_IsPrint(lead_char);
2454  if (print_char != DEF_YES) { /* Rtn NULL if lead char non-printable (see Note #6c). */
2455  return ((CPU_CHAR *)0);
2456  }
2457  }
2458 
2459 
2460  nbr_fmt = nbr;
2461  pstr_fmt = pstr;
2462 
2463  if (nbr_neg == DEF_YES) { /* If nbr neg ... */
2464  if (nbr_dig > 0) { /* ... & if at least one dig, ... */
2465  *pstr_fmt++ = '-'; /* ... prepend a neg sign. */
2466  }
2467  }
2468 
2469  pstr_fmt += nbr_dig; /* Start fmt from least significant dig. */
2470 
2471  if (nul != DEF_NO) { /* If NOT DISABLED, append NULL char (see Note #4). */
2472  *pstr_fmt = (CPU_CHAR)'\0';
2473  }
2474  pstr_fmt--;
2475 
2476  if (nbr_dig > 0) {
2477  for (i = 1; i <= nbr_dig; i++) { /* Fmt str for desired nbr digs. */
2478  if ((nbr_fmt > 0) || /* If fmt nbr > 0 (see Note #3c1), ... */
2479  (nbr_dig == 1) || /* ... OR exactly 1 dig to fmt (see Note #3c2), ... */
2480  (i == 1)) { /* ... OR on one's dig to fmt; ... */
2481  /* ... calc & fmt dig val; ... */
2482  nbr_dig_val = nbr_fmt % nbr_base;
2483  if (nbr_dig_val <= 9) {
2484  *pstr_fmt-- = (CPU_CHAR)(nbr_dig_val + '0');
2485  } else {
2486  if (lower_case != DEF_YES) {
2487  *pstr_fmt-- = (CPU_CHAR)((nbr_dig_val - 10) + 'A');
2488  } else {
2489  *pstr_fmt-- = (CPU_CHAR)((nbr_dig_val - 10) + 'a');
2490  }
2491  }
2492 
2493  } else if (lead_char != (CPU_CHAR)'\0') { /* ... else if avail, ... */
2494  *pstr_fmt-- = (CPU_CHAR)lead_char; /* ... fmt lead char. */
2495  }
2496 
2497  nbr_fmt /= nbr_base; /* Shift nbr to next more significant dig. */
2498  }
2499  }
2500 
2501 
2502  return (pstr); /* Rtn ptr to fmt'd str (see Note #6d). */
2503 }
2504 
2505 
2506 /*$PAGE*/
2507 /*
2508 *********************************************************************************************************
2509 * Str_ParseNbr_Int32()
2510 *
2511 * Description : Parse 32-bit integer from string.
2512 *
2513 * Argument(s) : pstr Pointer to string (see Notes #1 & #2a).
2514 *
2515 * pstr_next Pointer to a variable to ... :
2516 *
2517 * (a) Return a pointer to first character following the integer string,
2518 * if NO errors (see Note #2a2B2);
2519 * (b) Return a pointer to 'pstr',
2520 * otherwise (see Note #2a2A2).
2521 *
2522 * nbr_base Base of number to parse (see Notes #2a1B1 & #2a2B1).
2523 *
2524 * nbr_signed Indicates whether number to parse is signed :
2525 *
2526 * DEF_NO Number is unsigned.
2527 * DEF_YES Number is signed.
2528 *
2529 * pnbr_neg Pointer to a variable to return if the parsed (signed) number is negative :
2530 *
2531 * DEF_NO Number is non-negative.
2532 * DEF_YES Number is negative.
2533 *
2534 * Return(s) : Parsed integer, if integer parsed with NO overflow (see Note #2a3A).
2535 *
2536 * DEF_INT_32U_MAX_VAL, if integer parsed but overflowed (see Note #2a3A1).
2537 *
2538 * 0, otherwise (see Note #2a3B).
2539 *
2540 * Caller(s) : Str_ParseNbr_Int32U(),
2541 * Str_ParseNbr_Int32S().
2542 *
2543 * Note(s) : (1) String buffer NOT modified.
2544 *
2545 * (2) (a) IEEE Std 1003.1, 2004 Edition, Section 'strtol() : DESCRIPTION' states that "these
2546 * functions shall convert the initial portion of the string pointed to by 'str' to a
2547 * type long ... representation" :
2548 *
2549 * (1) "First, they decompose the input string into three parts" :
2550 *
2551 * (A) "An initial, possibly empty, sequence of white-space characters [as specified
2552 * by isspace()]."
2553 *
2554 * (1) "The subject sequence is defined as the longest initial subsequence of the
2555 * input string, starting with the first non-white-space character that is of
2556 * the expected form. The subject sequence shall contain no characters if the
2557 * input string is empty or consists entirely of white-space characters."
2558 *
2559 * (B) (1) "A subject sequence interpreted as an integer represented in some radix
2560 * determined by the value of 'base'" :
2561 *
2562 * (a) "If the value of 'base' is 0, the expected form of the subject sequence
2563 * is that of a decimal constant, octal constant, or hexadecimal constant" :
2564 *
2565 * (1) "A decimal constant begins with a non-zero digit, and consists of a
2566 * sequence of decimal digits."
2567 *
2568 * (2) "An octal constant consists of the prefix '0' optionally followed by
2569 * a sequence of the digits '0' to '7' only."
2570 *
2571 * (3) "A hexadecimal constant consists of the prefix '0x' or '0X' followed
2572 * by a sequence of the decimal digits and letters 'a' (or 'A') to 'f'
2573 * (or 'F') with values 10 to 15 respectively."
2574 *
2575 * (b) "If the value of 'base' is between 2 and 36, the expected form of the
2576 * subject sequence is a sequence of letters and digits representing an
2577 * integer with the radix specified by 'base'" :
2578 *
2579 * (1) (A) "The letters from 'a' (or 'A') to 'z' (or 'Z') inclusive are
2580 * ascribed the values 10 to 35"; ...
2581 * (B) "only letters whose ascribed values are less than that of base
2582 * are permitted."
2583 *
2584 * (2) (A) "If the value of 'base' is 16, the characters '0x' or '0X' may
2585 * optionally precede the sequence of letters and digits."
2586 *
2587 * (B) Although NO specification states that "if the value of 'base'
2588 * is" 8, the '0' character "may optionally precede the sequence
2589 * of letters and digits"; it seems reasonable to allow the '0'
2590 * character to be optionally parsed.
2591 *$PAGE*
2592 * (2) "A subject sequence .... may be preceded by a '+' or '-' sign."
2593 *
2594 * (a) It does NOT seem reasonable to parse & convert a negative number
2595 * integer string into an unsigned integer. However, a negative sign
2596 * for an unsigned integer will automatically be parsed as an invalid
2597 * character (see Note #2aC1).
2598 *
2599 * (C) (1) (a) "A final string of one or more unrecognized characters," ...
2600 * (b) "including the terminating null byte of the input string" ...
2601 * (2) "other than a sign or a permissible letter or digit."
2602 *
2603 * (2) Second, "they shall attempt to convert the subject sequence to an integer" :
2604 *
2605 * (A) "If the subject sequence is empty or does not have the expected form" :
2606 *
2607 * (1) "no conversion is performed"; ...
2608 * (2) "the value of 'str' is stored in the object pointed to by 'endptr',
2609 * provided that 'endptr' is not a null pointer."
2610 *
2611 * (B) "If the subject sequence has the expected form" :
2612 *
2613 * (1) (a) "and the value of 'base' is 0, the sequence of characters starting with
2614 * the first digit shall be interpreted as an integer constant."
2615 *
2616 * (b) "and the value of 'base' is between 2 and 36, it shall be used as the
2617 * base for conversion, ascribing to each letter its value as given above"
2618 * (see Note #2a1B1b1A).
2619 *
2620 * (2) "A pointer to the final string shall be stored in the object pointed to by
2621 * 'endptr', provided that 'endptr' is not a null pointer."
2622 *
2623 * (3) Lastly, IEEE Std 1003.1, 2004 Edition, Section 'strtol() : RETURN VALUE' states that :
2624 *
2625 * (A) "Upon successful completion, these functions shall return the converted value."
2626 * (1) "If the correct value is outside the range of representable values, {LONG_MIN}
2627 * [or] {LONG_MAX} ... shall be returned."
2628 *
2629 * (B) "If no conversion could be performed, 0 shall be returned."
2630 *
2631 * (b) (1) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
2632 * shall fail if" :
2633 *
2634 * (A) "[EINVAL] - The value of 'base' is not supported."
2635 *
2636 * (B) "[ERANGE] - The value to be returned is not representable."
2637 *
2638 * (2) IEEE Std 1003.1, 2004 Edition, Section 'strtoul() : ERRORS' states that "these functions
2639 * may fail if" :
2640 *
2641 * (A) "[EINVAL] - No conversion could be performed."
2642 *$PAGE*
2643 * (3) Return integer value & next string pointer should be used to diagnose parse success or failure :
2644 *
2645 * (a) Valid parse string integer :
2646 *
2647 * pstr = " ABCDE xyz"
2648 * nbr_base = 16
2649 *
2650 * nbr = 703710
2651 * pstr_next = " xyz"
2652 *
2653 *
2654 * (b) Invalid parse string integer :
2655 *
2656 * pstr = " ABCDE"
2657 * nbr_base = 10
2658 *
2659 * nbr = 0
2660 * pstr_next = pstr = " ABCDE"
2661 *
2662 *
2663 * (c) Valid hexadecimal parse string integer :
2664 *
2665 * pstr = " 0xGABCDE"
2666 * nbr_base = 16
2667 *
2668 * nbr = 0
2669 * pstr_next = "xGABCDE"
2670 *
2671 *
2672 * (d) Valid decimal parse string integer ('0x' prefix ignored
2673 * following invalid hexadecimal characters) :
2674 *
2675 * pstr = " 0xGABCDE"
2676 * nbr_base = 0
2677 *
2678 * nbr = 0
2679 * pstr_next = "xGABCDE"
2680 *
2681 *
2682 * (e) Valid decimal parse string integer ('0' prefix ignored
2683 * following invalid octal characters) :
2684 *
2685 * pstr = " 0GABCDE"
2686 * nbr_base = 0
2687 *
2688 * nbr = 0
2689 * pstr_next = "GABCDE"
2690 *
2691 *
2692 * (f) Parse string integer overflow :
2693 *
2694 * pstr = " 12345678901234567890*123456"
2695 * nbr_base = 10
2696 *
2697 * nbr = DEF_INT_32U_MAX_VAL
2698 * pstr_next = "*123456"
2699 *
2700 *
2701 * (g) Parse string integer underflow :
2702 *
2703 * pstr = " -12345678901234567890*123456"
2704 * nbr_base = 10
2705 *
2706 * nbr = DEF_INT_32S_MIN_VAL
2707 * pstr_next = "*123456"
2708 *
2709 *
2710 * (4) String parse terminates when :
2711 *
2712 * (a) Base passed an invalid base (see Note #2a1B1b).
2713 * (1) No conversion performed; zero returned.
2714 *
2715 * (b) (1) Parse string passed a NULL pointer OR empty integer sequence (see Note #2a2A).
2716 * (A) No conversion performed; zero returned.
2717 *
2718 * (2) Invalid parse string character found (see Note #2a1C).
2719 * (A) Parsed integer returned.
2720 * (B) 'pstr_next' points to invalid character.
2721 *
2722 * (3) Entire parse string converted (see Note #2a2B).
2723 * (A) Parsed integer returned.
2724 * (B) 'pstr_next' points to terminating NULL character.
2725 *
2726 * (5) Pointers to variables that return values MUST be initialized PRIOR to all other
2727 * validation or function handling in case of any error(s).
2728 *********************************************************************************************************
2729 */
2730 /*$PAGE*/
2732  CPU_CHAR **pstr_next,
2733  CPU_INT08U nbr_base,
2734  CPU_BOOLEAN nbr_signed,
2735  CPU_BOOLEAN *pnbr_neg)
2736 {
2737  CPU_CHAR *pstr_parse;
2738  CPU_CHAR *pstr_parse_nbr;
2739  CPU_CHAR parse_char;
2740  CPU_INT08U parse_dig;
2741  CPU_INT32U nbr;
2742  CPU_BOOLEAN nbr_dig;
2743  CPU_BOOLEAN nbr_alpha;
2744  CPU_BOOLEAN nbr_hex;
2745  CPU_BOOLEAN nbr_hex_lower;
2746  CPU_BOOLEAN whitespace;
2747  CPU_BOOLEAN neg;
2748  CPU_BOOLEAN ovf;
2749  CPU_BOOLEAN done;
2750 
2751  /* Init rtn vals for err (see Note #5). */
2752  if (pstr_next != (CPU_CHAR **)0) {
2753  *pstr_next = (CPU_CHAR *)pstr;
2754  }
2755 
2756  if (pnbr_neg != (CPU_BOOLEAN *)0) {
2757  *pnbr_neg = (CPU_BOOLEAN )DEF_NO;
2758  }
2759 
2760 
2761  if (pstr == (CPU_CHAR *)0) { /* Rtn zero if str ptr NULL (see Note #4b1). */
2762  return ((CPU_INT32U)0);
2763  }
2764  /* Rtn zero if invalid base (see Note #4a). */
2765  if ((nbr_base == 1) ||
2766  (nbr_base > 36)) {
2767  return ((CPU_INT32U)0);
2768  }
2769 
2770 
2771  /* ------------- IGNORE PRECEDING CHAR(S) ------------- */
2772  pstr_parse = pstr; /* Save ptr to init'l str for err (see Note #2a2A2). */
2773 
2774  whitespace = ASCII_IsSpace(*pstr_parse);
2775  while (whitespace == DEF_YES) { /* Ignore initial white-space char(s) [see Note #2a1A]. */
2776  pstr_parse++;
2777  whitespace = ASCII_IsSpace(*pstr_parse);
2778  }
2779 
2780  switch (*pstr_parse) {
2781  case '+': /* Ignore pos sign (see Note #2a1B2). */
2782  pstr_parse++;
2783  neg = DEF_NO;
2784  break;
2785 
2786 
2787  case '-': /* Validate neg sign (see Note #2a1B2a). */
2788  if (nbr_signed == DEF_YES) {
2789  pstr_parse++;
2790  }
2791  neg = DEF_YES;
2792  break;
2793 
2794 
2795  default:
2796  neg = DEF_NO;
2797  break;
2798  }
2799 
2800 
2801 /*$PAGE*/
2802  /* --------- IGNORE NBR BASE PRECEDING CHAR(S) -------- */
2803  pstr_parse_nbr = pstr_parse; /* Save ptr to str's nbr (see Note #2a1A1). */
2804 
2805  switch (nbr_base) {
2806  case 0: /* Determine unspecified nbr base (see Notes #2a1B1a). */
2807  if (*pstr_parse == '0') { /* If avail, ... */
2808  pstr_parse++; /* ... adv past '0' prefix (see Note #2a1B1b2). */
2809  switch (*pstr_parse) {
2810  case 'x': /* For '0x' prefix, ... */
2811  case 'X':
2812  nbr_base = 16; /* ... set nbr base = 16 (see Note #2a1B1a3). */
2813  parse_char = (CPU_CHAR)(*(pstr_parse + 1));
2814  nbr_hex = ASCII_IsDigHex(parse_char);
2815  if (nbr_hex == DEF_YES) { /* If next char is valid hex dig, ... */
2816  pstr_parse++; /* ... adv past '0x' prefix (see Note #2a1B1b2A). */
2817  }
2818  break;
2819 
2820 
2821  default: /* For '0' prefix, ... */
2822  nbr_base = 8; /* ... set nbr base = 8 (see Note #2a1B1a2). */
2823  break;
2824  }
2825 
2826  } else { /* For non-'0' prefix, ... */
2827  nbr_base = 10; /* ... set nbr base = 10 (see Note #2a1B1a1). */
2828  }
2829  break;
2830 
2831 
2832  case 8: /* See Note #2a1B1a2. */
2833  if (*pstr_parse == '0') { /* If avail, ... */
2834  pstr_parse++; /* ... adv past '0' prefix (see Note #2a1B1b2B). */
2835  }
2836  break;
2837 
2838 
2839  case 16: /* See Note #2a1B1a3. */
2840  if (*pstr_parse == '0') { /* If avail, ... */
2841  pstr_parse++; /* ... adv past '0' prefix (see Note #2a1B1b2). */
2842  switch (*pstr_parse) {
2843  case 'x':
2844  case 'X':
2845  parse_char = (CPU_CHAR)(*(pstr_parse + 1));
2846  nbr_hex = ASCII_IsDigHex(parse_char);
2847  if (nbr_hex == DEF_YES) { /* If next char is valid hex dig, ... */
2848  pstr_parse++; /* ... adv past '0x' prefix (see Note #2a1B1b2A). */
2849  }
2850  break;
2851 
2852 
2853  default:
2854  break;
2855  }
2856  }
2857  break;
2858 
2859 
2860  default: /* See Note #2a1B1b. */
2861  break;
2862  }
2863 
2864 
2865 /*$PAGE*/
2866  /* ------------------ PARSE INT STR ------------------- */
2867  nbr = 0;
2868  ovf = DEF_NO;
2869  done = DEF_NO;
2870 
2871  while (done == DEF_NO) { /* Parse str for desired nbr base digs (see Note #2a2). */
2872  parse_char = (CPU_CHAR)*pstr_parse;
2873  nbr_alpha = ASCII_IsAlphaNum(parse_char);
2874  if (nbr_alpha == DEF_YES) { /* If valid alpha num nbr dig avail, ... */
2875  /* ... convert parse char into nbr dig. */
2876  nbr_dig = ASCII_IsDig(parse_char);
2877  if (nbr_dig == DEF_YES) {
2878  parse_dig = (CPU_INT08U)(parse_char - '0');
2879  } else {
2880  nbr_hex_lower = ASCII_IsLower(parse_char);
2881  if (nbr_hex_lower == DEF_YES) {
2882  parse_dig = (CPU_INT08U)((parse_char - 'a') + 10);
2883  } else {
2884  parse_dig = (CPU_INT08U)((parse_char - 'A') + 10);
2885  }
2886  }
2887 
2888  if (parse_dig < nbr_base) { /* If parse char valid for nbr base ... */
2889  if (ovf == DEF_NO) { /* ... & nbr NOT yet ovf'd, ... */
2890  if (nbr <= Str_MultOvfThTbl_Int32U[nbr_base]) {
2891  /* ... merge parse char dig into nbr. */
2892  nbr *= nbr_base;
2893  nbr += parse_dig;
2894  if (nbr < parse_dig) {
2895  ovf = DEF_YES;
2896  }
2897  } else {
2898  ovf = DEF_YES;
2899  }
2900  }
2901  pstr_parse++;
2902 
2903  } else { /* Invalid char parsed (see Note #2a1C1a). */
2904  done = DEF_YES;
2905  }
2906 
2907  } else { /* Invalid OR NULL char parsed (see Note #2a1C1). */
2908  done = DEF_YES;
2909  }
2910  }
2911 
2912  if (ovf == DEF_YES) { /* If nbr ovf'd, ... */
2913  nbr = DEF_INT_32U_MAX_VAL; /* ... rtn max int val (see Note #2a3A1). */
2914  }
2915 
2916 
2917  if (pstr_next != (CPU_CHAR **)0) {
2918  if (pstr_parse != pstr_parse_nbr) { /* If final parse str != init'l parse nbr str, .. */
2919  *pstr_next = pstr_parse; /* .. rtn parse str's next char (see Note #2a2B2); .. */
2920  } else {
2921  *pstr_next = pstr; /* .. else rtn initial parse str (see Note #2a2A2). */
2922  }
2923  }
2924 
2925  if (pnbr_neg != (CPU_BOOLEAN *)0) {
2926  *pnbr_neg = (CPU_BOOLEAN )neg; /* Rtn neg nbr status. */
2927  }
2928 
2929 
2930  return (nbr);
2931 }
2932