1 //*****************************************************************************
\r
3 // ustdlib.c - Simple standard library functions.
\r
5 // Copyright (c) 2007 Luminary Micro, Inc. All rights reserved.
\r
7 // Software License Agreement
\r
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
\r
10 // exclusively on LMI's microcontroller products.
\r
12 // The software is owned by LMI and/or its suppliers, and is protected under
\r
13 // applicable copyright laws. All rights are reserved. Any use in violation
\r
14 // of the foregoing restrictions may subject the user to criminal sanctions
\r
15 // under applicable laws, as well as to civil liability for the breach of the
\r
16 // terms and conditions of this license.
\r
18 // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
\r
19 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
\r
20 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
\r
21 // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
\r
22 // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
\r
24 //*****************************************************************************
\r
30 //*****************************************************************************
\r
32 //! \addtogroup utilities_api
\r
35 //*****************************************************************************
\r
37 //*****************************************************************************
\r
39 // A mapping from an integer between 0 and 15 to its ASCII character
\r
42 //*****************************************************************************
\r
43 static const char * const g_pcHex = "0123456789abcdef";
\r
45 //*****************************************************************************
\r
47 //! A simple sprintf function supporting \%c, \%d, \%s, \%u, \%x, and \%X.
\r
49 //! \param pcBuf is the buffer where the converted string is stored.
\r
50 //! \param pcString is the format string.
\r
51 //! \param ... are the optional arguments, which depend on the contents of the
\r
54 //! This function is very similar to the C library <tt>sprintf()</tt> function.
\r
55 //! Only the following formatting characters are supported:
\r
57 //! - \%c to print a character
\r
58 //! - \%d to print a decimal value
\r
59 //! - \%s to print a string
\r
60 //! - \%u to print an unsigned decimal value
\r
61 //! - \%x to print a hexadecimal value using lower case letters
\r
62 //! - \%X to print a hexadecimal value using lower case letters (not upper case
\r
63 //! letters as would typically be used)
\r
64 //! - \%\% to print out a \% character
\r
66 //! For \%d, \%u, \%x, and \%X, an optional number may reside between the \%
\r
67 //! and the format character, which specifies the minimum number of characters
\r
68 //! to use for that value; if preceeded by a 0 then the extra characters will
\r
69 //! be filled with zeros instead of spaces. For example, ``\%8d'' will use
\r
70 //! eight characters to print the decimal value with spaces added to reach
\r
71 //! eight; ``\%08d'' will use eight characters as well but will add zeros
\r
72 //! instead of spaces.
\r
74 //! The type of the arguments after \b pcString must match the requirements of
\r
75 //! the format string. For example, if an integer was passed where a string
\r
76 //! was expected, an error of some kind will most likely occur.
\r
78 //! The caller must ensure that the buffer pcBuf is large enough to hold the
\r
79 //! entire converted string, including the null termination character.
\r
83 //*****************************************************************************
\r
85 uvsnprintf(char *pcBuf, unsigned long ulSize, const char *pcString,
\r
88 unsigned long ulIdx, ulValue, ulPos, ulCount, ulBase;
\r
89 char *pcStr, cFill, *pcOriginalBuf = pcBuf;
\r
92 // Check the arguments.
\r
94 ASSERT(pcString != 0);
\r
96 ASSERT(ulSize != 0);
\r
99 // Adjust buffer size limit to allow one space for null termination.
\r
107 // Loop while there are more characters in the string, and
\r
108 // there is more room in the destination buffer.
\r
110 while(*pcString && ulSize)
\r
113 // Find the first non-% character, or the end of the string.
\r
115 for(ulIdx = 0; (pcString[ulIdx] != '%') && (pcString[ulIdx] != '\0');
\r
121 // Limit the number of characters that can be copied to the
\r
122 // space remaining in the buffer.
\r
130 // Write this portion of the string and update the buffer pointer.
\r
132 strncpy(pcBuf, pcString, ulIdx);
\r
136 // Update the size limit, and check to see if the buffer
\r
137 // limit is reached.
\r
146 // Skip the portion of the string that was written.
\r
151 // See if the next character is a %.
\r
153 if(*pcString == '%')
\r
161 // Set the digit count to zero, and the fill character to space
\r
162 // (i.e. to the defaults).
\r
168 // It may be necessary to get back here to process more characters.
\r
169 // Goto's aren't pretty, but effective. I feel extremely dirty for
\r
170 // using not one but two of the beasts.
\r
175 // Determine how to handle the next character.
\r
177 switch(*pcString++)
\r
180 // Handle the digit characters.
\r
194 // If this is a zero, and it is the first digit, then the
\r
195 // fill character is a zero instead of a space.
\r
197 if((pcString[-1] == '0') && (ulCount == 0))
\r
203 // Update the digit count.
\r
206 ulCount += pcString[-1] - '0';
\r
209 // Get the next character.
\r
215 // Handle the %c command.
\r
220 // Get the value from the varargs.
\r
222 ulValue = va_arg(vaArgP, unsigned long);
\r
225 // Print out the character.
\r
227 *pcBuf++ = (char)ulValue;
\r
230 // Decrement the buffer limit.
\r
235 // This command has been handled.
\r
241 // Handle the %d command.
\r
246 // Get the value from the varargs.
\r
248 ulValue = va_arg(vaArgP, unsigned long);
\r
251 // Reset the buffer position.
\r
256 // If the value is negative, make it positive and stick a
\r
257 // minus sign in the beginning of the buffer.
\r
259 if((long)ulValue < 0)
\r
263 ulValue = -(long)ulValue;
\r
266 // Decrement the buffer size limit and check
\r
267 // if the limit is reached.
\r
277 // Set the base to 10.
\r
282 // Convert the value to ASCII.
\r
288 // Handle the %s command.
\r
293 // Get the string pointer from the varargs.
\r
295 pcStr = va_arg(vaArgP, char *);
\r
298 // Determine the length of the string.
\r
300 for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++)
\r
305 // Limit the number of characters that can be copied to the
\r
306 // space remaining in the buffer.
\r
314 // Write the string and update the buffer pointer.
\r
316 strncpy(pcBuf, pcStr, ulIdx);
\r
320 // Decrement the buffer size limit.
\r
326 // This command has been handled.
\r
332 // Handle the %u command.
\r
337 // Get the value from the varargs.
\r
339 ulValue = va_arg(vaArgP, unsigned long);
\r
342 // Reset the buffer position.
\r
347 // Set the base to 10.
\r
352 // Convert the value to ASCII.
\r
358 // Handle the %x and %X commands. Note that they are treated
\r
359 // identically; i.e. %X will use lower case letters for a-f
\r
360 // instead of the upper case letters is should use.
\r
366 // Get the value from the varargs.
\r
368 ulValue = va_arg(vaArgP, unsigned long);
\r
371 // Reset the buffer position.
\r
376 // Set the base to 16.
\r
381 // Determine the number of digits in the string version of
\r
386 (((ulIdx * ulBase) <= ulValue) &&
\r
387 (((ulIdx * ulBase) / ulBase) == ulIdx));
\r
388 ulIdx *= ulBase, ulCount--)
\r
393 // Provide additional padding at the beginning of the
\r
394 // string conversion if needed.
\r
396 if((ulCount > 1) && (ulCount < 16))
\r
398 for(ulCount--; ulCount; ulCount--)
\r
404 // Decrement buffer size and check to see if
\r
405 // buffer limit is reached.
\r
416 // Convert the value into a string.
\r
418 for(; ulIdx; ulIdx /= ulBase)
\r
420 *pcBuf++ = g_pcHex[(ulValue / ulIdx) % ulBase];
\r
424 // Decrement buffer size and check to see if
\r
425 // buffer limit is reached.
\r
435 // This command has been handled.
\r
441 // Handle the %% command.
\r
446 // Simply write a single %.
\r
448 *pcBuf++ = pcString[-1];
\r
452 // This command has been handled.
\r
458 // Handle all other commands.
\r
463 // Indicate an error.
\r
467 strncpy(pcBuf, "ERROR", 5);
\r
473 // This command has been handled.
\r
482 // Null terminate the string in the buffer.
\r
485 return ( int ) pcBuf - ( int ) pcOriginalBuf;
\r
488 //*****************************************************************************
\r
490 //! A simple sprintf function supporting \%c, \%d, \%s, \%u, \%x, and \%X.
\r
492 //! \param pcBuf is the buffer where the converted string is stored.
\r
493 //! \param pcString is the format string.
\r
494 //! \param ... are the optional arguments, which depend on the contents of the
\r
497 //! This function is very similar to the C library <tt>sprintf()</tt> function.
\r
498 //! Only the following formatting characters are supported:
\r
500 //! - \%c to print a character
\r
501 //! - \%d to print a decimal value
\r
502 //! - \%s to print a string
\r
503 //! - \%u to print an unsigned decimal value
\r
504 //! - \%x to print a hexadecimal value using lower case letters
\r
505 //! - \%X to print a hexadecimal value using lower case letters (not upper case
\r
506 //! letters as would typically be used)
\r
507 //! - \%\% to print out a \% character
\r
509 //! For \%d, \%u, \%x, and \%X, an optional number may reside between the \%
\r
510 //! and the format character, which specifies the minimum number of characters
\r
511 //! to use for that value; if preceeded by a 0 then the extra characters will
\r
512 //! be filled with zeros instead of spaces. For example, ``\%8d'' will use
\r
513 //! eight characters to print the decimal value with spaces added to reach
\r
514 //! eight; ``\%08d'' will use eight characters as well but will add zeros
\r
515 //! instead of spaces.
\r
517 //! The type of the arguments after \b pcString must match the requirements of
\r
518 //! the format string. For example, if an integer was passed where a string
\r
519 //! was expected, an error of some kind will most likely occur.
\r
521 //! The caller must ensure that the buffer pcBuf is large enough to hold the
\r
522 //! entire converted string, including the null termination character.
\r
526 //*****************************************************************************
\r
528 usprintf(char *pcBuf, const char *pcString, ...)
\r
533 // Start the varargs processing.
\r
535 va_start(vaArgP, pcString);
\r
538 // Call vsnprintf to perform the conversion. Use a
\r
539 // large number for the buffer size.
\r
541 uvsnprintf(pcBuf, 0xffff, pcString, vaArgP);
\r
544 // End the varargs processing.
\r
549 //*****************************************************************************
\r
551 //! A simple snprintf function supporting \%c, \%d, \%s, \%u, \%x, and \%X.
\r
553 //! \param pcBuf is the buffer where the converted string is stored.
\r
554 //! \param ulSize is the size of the buffer.
\r
555 //! \param pcString is the format string.
\r
556 //! \param ... are the optional arguments, which depend on the contents of the
\r
559 //! This function is very similar to the C library <tt>sprintf()</tt> function.
\r
560 //! Only the following formatting characters are supported:
\r
562 //! - \%c to print a character
\r
563 //! - \%d to print a decimal value
\r
564 //! - \%s to print a string
\r
565 //! - \%u to print an unsigned decimal value
\r
566 //! - \%x to print a hexadecimal value using lower case letters
\r
567 //! - \%X to print a hexadecimal value using lower case letters (not upper case
\r
568 //! letters as would typically be used)
\r
569 //! - \%\% to print out a \% character
\r
571 //! For \%d, \%u, \%x, and \%X, an optional number may reside between the \%
\r
572 //! and the format character, which specifies the minimum number of characters
\r
573 //! to use for that value; if preceeded by a 0 then the extra characters will
\r
574 //! be filled with zeros instead of spaces. For example, ``\%8d'' will use
\r
575 //! eight characters to print the decimal value with spaces added to reach
\r
576 //! eight; ``\%08d'' will use eight characters as well but will add zeros
\r
577 //! instead of spaces.
\r
579 //! The type of the arguments after \b pcString must match the requirements of
\r
580 //! the format string. For example, if an integer was passed where a string
\r
581 //! was expected, an error of some kind will most likely occur.
\r
583 //! The function will copy at most \b ulSize - 1 characters into the
\r
584 //! buffer \b pcBuf. One space is reserved in the buffer for the null
\r
585 //! termination character.
\r
589 //*****************************************************************************
\r
591 usnprintf(char *pcBuf, unsigned long ulSize, const char *pcString, ...)
\r
598 // Start the varargs processing.
\r
600 va_start(vaArgP, pcString);
\r
603 // Call vsnprintf to perform the conversion.
\r
605 iReturn = uvsnprintf(pcBuf, ulSize, pcString, vaArgP);
\r
608 // End the varargs processing.
\r
615 //*****************************************************************************
\r
617 // Close the Doxygen group.
\r
620 //*****************************************************************************
\r