]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_LM3S2965_GCC/LuminaryDrivers/ustdlib.c
Update to V4.3.0 as described in http://www.FreeRTOS.org/History.txt
[freertos] / Demo / CORTEX_LM3S2965_GCC / LuminaryDrivers / ustdlib.c
1 //*****************************************************************************\r
2 //\r
3 // ustdlib.c - Simple standard library functions.\r
4 //\r
5 // Copyright (c) 2007 Luminary Micro, Inc.  All rights reserved.\r
6 // \r
7 // Software License Agreement\r
8 // \r
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and\r
10 // exclusively on LMI's microcontroller products.\r
11 // \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
17 // \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
23 // \r
24 //*****************************************************************************\r
25 \r
26 #include <stdarg.h>\r
27 #include <string.h>\r
28 #include "debug.h"\r
29 \r
30 //*****************************************************************************\r
31 //\r
32 //! \addtogroup utilities_api\r
33 //! @{\r
34 //\r
35 //*****************************************************************************\r
36 \r
37 //*****************************************************************************\r
38 //\r
39 // A mapping from an integer between 0 and 15 to its ASCII character\r
40 // equivalent.\r
41 //\r
42 //*****************************************************************************\r
43 static const char * const g_pcHex = "0123456789abcdef";\r
44 \r
45 //*****************************************************************************\r
46 //\r
47 //! A simple sprintf function supporting \%c, \%d, \%s, \%u, \%x, and \%X.\r
48 //!\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
52 //! format string.\r
53 //!\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
56 //!\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
65 //!\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
73 //!\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
77 //!\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
80 //!\r
81 //! \return None.\r
82 //\r
83 //*****************************************************************************\r
84 void\r
85 usprintf(char *pcBuf, const char *pcString, ...)\r
86 {\r
87     unsigned long ulIdx, ulValue, ulPos, ulCount, ulBase;\r
88     char *pcStr, cFill;\r
89     va_list vaArgP;\r
90 \r
91     //\r
92     // Check the arguments.\r
93     //\r
94     ASSERT(pcString != 0);\r
95     ASSERT(pcBuf != 0);\r
96 \r
97     //\r
98     // Start the varargs processing.\r
99     //\r
100     va_start(vaArgP, pcString);\r
101 \r
102     //\r
103     // Loop while there are more characters in the string.\r
104     //\r
105     while(*pcString)\r
106     {\r
107         //\r
108         // Find the first non-% character, or the end of the string.\r
109         //\r
110         for(ulIdx = 0; (pcString[ulIdx] != '%') && (pcString[ulIdx] != '\0');\r
111             ulIdx++)\r
112         {\r
113         }\r
114 \r
115         //\r
116         // Write this portion of the string.\r
117         //\r
118         strncpy(pcBuf, pcString, ulIdx);\r
119 \r
120         //\r
121         // Skip the portion of the string that was written.\r
122         //\r
123         pcString += ulIdx;\r
124         pcBuf += ulIdx;\r
125 \r
126         //\r
127         // See if the next character is a %.\r
128         //\r
129         if(*pcString == '%')\r
130         {\r
131             //\r
132             // Skip the %.\r
133             //\r
134             pcString++;\r
135 \r
136             //\r
137             // Set the digit count to zero, and the fill character to space\r
138             // (i.e. to the defaults).\r
139             //\r
140             ulCount = 0;\r
141             cFill = ' ';\r
142 \r
143             //\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
147             //\r
148 again:\r
149 \r
150             //\r
151             // Determine how to handle the next character.\r
152             //\r
153             switch(*pcString++)\r
154             {\r
155                 //\r
156                 // Handle the digit characters.\r
157                 //\r
158                 case '0':\r
159                 case '1':\r
160                 case '2':\r
161                 case '3':\r
162                 case '4':\r
163                 case '5':\r
164                 case '6':\r
165                 case '7':\r
166                 case '8':\r
167                 case '9':\r
168                 {\r
169                     //\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
172                     //\r
173                     if((pcString[-1] == '0') && (ulCount == 0))\r
174                     {\r
175                         cFill = '0';\r
176                     }\r
177 \r
178                     //\r
179                     // Update the digit count.\r
180                     //\r
181                     ulCount *= 10;\r
182                     ulCount += pcString[-1] - '0';\r
183 \r
184                     //\r
185                     // Get the next character.\r
186                     //\r
187                     goto again;\r
188                 }\r
189 \r
190                 //\r
191                 // Handle the %c command.\r
192                 //\r
193                 case 'c':\r
194                 {\r
195                     //\r
196                     // Get the value from the varargs.\r
197                     //\r
198                     ulValue = va_arg(vaArgP, unsigned long);\r
199 \r
200                     //\r
201                     // Print out the character.\r
202                     //\r
203                     *pcBuf++ = (char)ulValue;\r
204 \r
205                     //\r
206                     // This command has been handled.\r
207                     //\r
208                     break;\r
209                 }\r
210 \r
211                 //\r
212                 // Handle the %d command.\r
213                 //\r
214                 case 'd':\r
215                 {\r
216                     //\r
217                     // Get the value from the varargs.\r
218                     //\r
219                     ulValue = va_arg(vaArgP, unsigned long);\r
220 \r
221                     //\r
222                     // Reset the buffer position.\r
223                     //\r
224                     ulPos = 0;\r
225 \r
226                     //\r
227                     // If the value is negative, make it positive and stick a\r
228                     // minus sign in the beginning of the buffer.\r
229                     //\r
230                     if((long)ulValue < 0)\r
231                     {\r
232                         *pcBuf++ = '-';\r
233                         ulPos++;\r
234                         ulValue = -(long)ulValue;\r
235                     }\r
236 \r
237                     //\r
238                     // Set the base to 10.\r
239                     //\r
240                     ulBase = 10;\r
241 \r
242                     //\r
243                     // Convert the value to ASCII.\r
244                     //\r
245                     goto convert;\r
246                 }\r
247 \r
248                 //\r
249                 // Handle the %s command.\r
250                 //\r
251                 case 's':\r
252                 {\r
253                     //\r
254                     // Get the string pointer from the varargs.\r
255                     //\r
256                     pcStr = va_arg(vaArgP, char *);\r
257 \r
258                     //\r
259                     // Determine the length of the string.\r
260                     //\r
261                     for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++)\r
262                     {\r
263                     }\r
264 \r
265                     //\r
266                     // Write the string.\r
267                     //\r
268                     strncpy(pcBuf, pcStr, ulIdx);\r
269                     pcBuf += ulIdx;\r
270 \r
271                     //\r
272                     // This command has been handled.\r
273                     //\r
274                     break;\r
275                 }\r
276 \r
277                 //\r
278                 // Handle the %u command.\r
279                 //\r
280                 case 'u':\r
281                 {\r
282                     //\r
283                     // Get the value from the varargs.\r
284                     //\r
285                     ulValue = va_arg(vaArgP, unsigned long);\r
286 \r
287                     //\r
288                     // Reset the buffer position.\r
289                     //\r
290                     ulPos = 0;\r
291 \r
292                     //\r
293                     // Set the base to 10.\r
294                     //\r
295                     ulBase = 10;\r
296 \r
297                     //\r
298                     // Convert the value to ASCII.\r
299                     //\r
300                     goto convert;\r
301                 }\r
302 \r
303                 //\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
307                 //\r
308                 case 'x':\r
309                 case 'X':\r
310                 {\r
311                     //\r
312                     // Get the value from the varargs.\r
313                     //\r
314                     ulValue = va_arg(vaArgP, unsigned long);\r
315 \r
316                     //\r
317                     // Reset the buffer position.\r
318                     //\r
319                     ulPos = 0;\r
320 \r
321                     //\r
322                     // Set the base to 16.\r
323                     //\r
324                     ulBase = 16;\r
325 \r
326                     //\r
327                     // Determine the number of digits in the string version of\r
328                     // the value.\r
329                     //\r
330 convert:\r
331                     for(ulIdx = 1;\r
332                         (((ulIdx * ulBase) <= ulValue) &&\r
333                          (((ulIdx * ulBase) / ulBase) == ulIdx));\r
334                         ulIdx *= ulBase, ulCount--)\r
335                     {\r
336                     }\r
337 \r
338                     //\r
339                     // Provide additional padding at the beginning of the\r
340                     // string conversion if needed.\r
341                     //\r
342                     if((ulCount > 1) && (ulCount < 16))\r
343                     {\r
344                         for(ulCount--; ulCount; ulCount--)\r
345                         {\r
346                             *pcBuf++ = cFill;\r
347                             ulPos++;\r
348                         }\r
349                     }\r
350 \r
351                     //\r
352                     // Convert the value into a string.\r
353                     //\r
354                     for(; ulIdx; ulIdx /= ulBase)\r
355                     {\r
356                         *pcBuf++ = g_pcHex[(ulValue / ulIdx) % ulBase];\r
357                         ulPos++;\r
358                     }\r
359 \r
360                     //\r
361                     // This command has been handled.\r
362                     //\r
363                     break;\r
364                 }\r
365 \r
366                 //\r
367                 // Handle the %% command.\r
368                 //\r
369                 case '%':\r
370                 {\r
371                     //\r
372                     // Simply write a single %.\r
373                     //\r
374                     *pcBuf++ = pcString[-1];\r
375 \r
376                     //\r
377                     // This command has been handled.\r
378                     //\r
379                     break;\r
380                 }\r
381 \r
382                 //\r
383                 // Handle all other commands.\r
384                 //\r
385                 default:\r
386                 {\r
387                     //\r
388                     // Indicate an error.\r
389                     //\r
390                     strncpy(pcBuf, "ERROR", 5);\r
391                     pcBuf += 5;\r
392 \r
393                     //\r
394                     // This command has been handled.\r
395                     //\r
396                     break;\r
397                 }\r
398             }\r
399         }\r
400     }\r
401 \r
402     //\r
403     // End the varargs processing.\r
404     //\r
405     va_end(vaArgP);\r
406 \r
407     //\r
408     // Null terminate the string in the buffer.\r
409     //\r
410     *pcBuf = 0;\r
411 }\r
412 \r
413 //*****************************************************************************\r
414 //\r
415 // Close the Doxygen group.\r
416 //! @}\r
417 //\r
418 //*****************************************************************************\r