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 usprintf(char *pcBuf, const char *pcString, ...)
\r
87 unsigned long ulIdx, ulValue, ulPos, ulCount, ulBase;
\r
92 // Check the arguments.
\r
94 ASSERT(pcString != 0);
\r
98 // Start the varargs processing.
\r
100 va_start(vaArgP, pcString);
\r
103 // Loop while there are more characters in the string.
\r
108 // Find the first non-% character, or the end of the string.
\r
110 for(ulIdx = 0; (pcString[ulIdx] != '%') && (pcString[ulIdx] != '\0');
\r
116 // Write this portion of the string.
\r
118 strncpy(pcBuf, pcString, ulIdx);
\r
121 // Skip the portion of the string that was written.
\r
127 // See if the next character is a %.
\r
129 if(*pcString == '%')
\r
137 // Set the digit count to zero, and the fill character to space
\r
138 // (i.e. to the defaults).
\r
144 // It may be necessary to get back here to process more characters.
\r
145 // Goto's aren't pretty, but effective. I feel extremely dirty for
\r
146 // using not one but two of the beasts.
\r
151 // Determine how to handle the next character.
\r
153 switch(*pcString++)
\r
156 // Handle the digit characters.
\r
170 // If this is a zero, and it is the first digit, then the
\r
171 // fill character is a zero instead of a space.
\r
173 if((pcString[-1] == '0') && (ulCount == 0))
\r
179 // Update the digit count.
\r
182 ulCount += pcString[-1] - '0';
\r
185 // Get the next character.
\r
191 // Handle the %c command.
\r
196 // Get the value from the varargs.
\r
198 ulValue = va_arg(vaArgP, unsigned long);
\r
201 // Print out the character.
\r
203 *pcBuf++ = (char)ulValue;
\r
206 // This command has been handled.
\r
212 // Handle the %d command.
\r
217 // Get the value from the varargs.
\r
219 ulValue = va_arg(vaArgP, unsigned long);
\r
222 // Reset the buffer position.
\r
227 // If the value is negative, make it positive and stick a
\r
228 // minus sign in the beginning of the buffer.
\r
230 if((long)ulValue < 0)
\r
234 ulValue = -(long)ulValue;
\r
238 // Set the base to 10.
\r
243 // Convert the value to ASCII.
\r
249 // Handle the %s command.
\r
254 // Get the string pointer from the varargs.
\r
256 pcStr = va_arg(vaArgP, char *);
\r
259 // Determine the length of the string.
\r
261 for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++)
\r
266 // Write the string.
\r
268 strncpy(pcBuf, pcStr, ulIdx);
\r
272 // This command has been handled.
\r
278 // Handle the %u command.
\r
283 // Get the value from the varargs.
\r
285 ulValue = va_arg(vaArgP, unsigned long);
\r
288 // Reset the buffer position.
\r
293 // Set the base to 10.
\r
298 // Convert the value to ASCII.
\r
304 // Handle the %x and %X commands. Note that they are treated
\r
305 // identically; i.e. %X will use lower case letters for a-f
\r
306 // instead of the upper case letters is should use.
\r
312 // Get the value from the varargs.
\r
314 ulValue = va_arg(vaArgP, unsigned long);
\r
317 // Reset the buffer position.
\r
322 // Set the base to 16.
\r
327 // Determine the number of digits in the string version of
\r
332 (((ulIdx * ulBase) <= ulValue) &&
\r
333 (((ulIdx * ulBase) / ulBase) == ulIdx));
\r
334 ulIdx *= ulBase, ulCount--)
\r
339 // Provide additional padding at the beginning of the
\r
340 // string conversion if needed.
\r
342 if((ulCount > 1) && (ulCount < 16))
\r
344 for(ulCount--; ulCount; ulCount--)
\r
352 // Convert the value into a string.
\r
354 for(; ulIdx; ulIdx /= ulBase)
\r
356 *pcBuf++ = g_pcHex[(ulValue / ulIdx) % ulBase];
\r
361 // This command has been handled.
\r
367 // Handle the %% command.
\r
372 // Simply write a single %.
\r
374 *pcBuf++ = pcString[-1];
\r
377 // This command has been handled.
\r
383 // Handle all other commands.
\r
388 // Indicate an error.
\r
390 strncpy(pcBuf, "ERROR", 5);
\r
394 // This command has been handled.
\r
403 // End the varargs processing.
\r
408 // Null terminate the string in the buffer.
\r
413 //*****************************************************************************
\r
415 // Close the Doxygen group.
\r
418 //*****************************************************************************
\r