]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_LM3S6965_GCC/LuminaryDrivers/ustdlib.c
Update to V4.3.0 as described in http://www.FreeRTOS.org/History.txt
[freertos] / Demo / CORTEX_LM3S6965_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 int\r
85 uvsnprintf(char *pcBuf, unsigned long ulSize, const char *pcString,\r
86            va_list vaArgP)\r
87 {\r
88     unsigned long ulIdx, ulValue, ulPos, ulCount, ulBase;\r
89     char *pcStr, cFill, *pcOriginalBuf = pcBuf;\r
90 \r
91     //\r
92     // Check the arguments.\r
93     //\r
94     ASSERT(pcString != 0);\r
95     ASSERT(pcBuf != 0);\r
96     ASSERT(ulSize != 0);\r
97 \r
98     //\r
99     // Adjust buffer size limit to allow one space for null termination.\r
100     //\r
101     if(ulSize)\r
102     {\r
103         ulSize--;\r
104     }\r
105 \r
106     //\r
107     // Loop while there are more characters in the string, and\r
108     // there is more room in the destination buffer.\r
109     //\r
110     while(*pcString && ulSize)\r
111     {\r
112         //\r
113         // Find the first non-% character, or the end of the string.\r
114         //\r
115         for(ulIdx = 0; (pcString[ulIdx] != '%') && (pcString[ulIdx] != '\0');\r
116             ulIdx++)\r
117         {\r
118         }\r
119 \r
120         //\r
121         // Limit the number of characters that can be copied to the\r
122         // space remaining in the buffer.\r
123         //\r
124         if(ulIdx > ulSize)\r
125         {\r
126             ulIdx = ulSize;\r
127         }\r
128 \r
129         //\r
130         // Write this portion of the string and update the buffer pointer.\r
131         //\r
132         strncpy(pcBuf, pcString, ulIdx);\r
133         pcBuf += ulIdx;\r
134 \r
135         //\r
136         // Update the size limit, and check to see if the buffer\r
137         // limit is reached.\r
138         //\r
139         ulSize -= ulIdx;\r
140         if(ulSize == 0)\r
141         {\r
142             break;\r
143         }\r
144 \r
145         //\r
146         // Skip the portion of the string that was written.\r
147         //\r
148         pcString += ulIdx;\r
149 \r
150         //\r
151         // See if the next character is a %.\r
152         //\r
153         if(*pcString == '%')\r
154         {\r
155             //\r
156             // Skip the %.\r
157             //\r
158             pcString++;\r
159 \r
160             //\r
161             // Set the digit count to zero, and the fill character to space\r
162             // (i.e. to the defaults).\r
163             //\r
164             ulCount = 0;\r
165             cFill = ' ';\r
166 \r
167             //\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
171             //\r
172 again:\r
173 \r
174             //\r
175             // Determine how to handle the next character.\r
176             //\r
177             switch(*pcString++)\r
178             {\r
179                 //\r
180                 // Handle the digit characters.\r
181                 //\r
182                 case '0':\r
183                 case '1':\r
184                 case '2':\r
185                 case '3':\r
186                 case '4':\r
187                 case '5':\r
188                 case '6':\r
189                 case '7':\r
190                 case '8':\r
191                 case '9':\r
192                 {\r
193                     //\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
196                     //\r
197                     if((pcString[-1] == '0') && (ulCount == 0))\r
198                     {\r
199                         cFill = '0';\r
200                     }\r
201 \r
202                     //\r
203                     // Update the digit count.\r
204                     //\r
205                     ulCount *= 10;\r
206                     ulCount += pcString[-1] - '0';\r
207 \r
208                     //\r
209                     // Get the next character.\r
210                     //\r
211                     goto again;\r
212                 }\r
213 \r
214                 //\r
215                 // Handle the %c command.\r
216                 //\r
217                 case 'c':\r
218                 {\r
219                     //\r
220                     // Get the value from the varargs.\r
221                     //\r
222                     ulValue = va_arg(vaArgP, unsigned long);\r
223 \r
224                     //\r
225                     // Print out the character.\r
226                     //\r
227                     *pcBuf++ = (char)ulValue;\r
228 \r
229                     //\r
230                     // Decrement the buffer limit.\r
231                     //\r
232                     ulSize--;\r
233 \r
234                     //\r
235                     // This command has been handled.\r
236                     //\r
237                     break;\r
238                 }\r
239 \r
240                 //\r
241                 // Handle the %d command.\r
242                 //\r
243                 case 'd':\r
244                 {\r
245                     //\r
246                     // Get the value from the varargs.\r
247                     //\r
248                     ulValue = va_arg(vaArgP, unsigned long);\r
249 \r
250                     //\r
251                     // Reset the buffer position.\r
252                     //\r
253                     ulPos = 0;\r
254 \r
255                     //\r
256                     // If the value is negative, make it positive and stick a\r
257                     // minus sign in the beginning of the buffer.\r
258                     //\r
259                     if((long)ulValue < 0)\r
260                     {\r
261                         *pcBuf++ = '-';\r
262                         ulPos++;\r
263                         ulValue = -(long)ulValue;\r
264 \r
265                         //\r
266                         // Decrement the buffer size limit and check\r
267                         // if the limit is reached.\r
268                         //\r
269                         ulSize--;\r
270                         if(ulSize == 0)\r
271                         {\r
272                             break;\r
273                         }\r
274                     }\r
275 \r
276                     //\r
277                     // Set the base to 10.\r
278                     //\r
279                     ulBase = 10;\r
280 \r
281                     //\r
282                     // Convert the value to ASCII.\r
283                     //\r
284                     goto convert;\r
285                 }\r
286 \r
287                 //\r
288                 // Handle the %s command.\r
289                 //\r
290                 case 's':\r
291                 {\r
292                     //\r
293                     // Get the string pointer from the varargs.\r
294                     //\r
295                     pcStr = va_arg(vaArgP, char *);\r
296 \r
297                     //\r
298                     // Determine the length of the string.\r
299                     //\r
300                     for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++)\r
301                     {\r
302                     }\r
303 \r
304                     //\r
305                     // Limit the number of characters that can be copied to the\r
306                     // space remaining in the buffer.\r
307                     //\r
308                     if(ulIdx > ulSize)\r
309                     {\r
310                         ulIdx = ulSize;\r
311                     }\r
312 \r
313                     //\r
314                     // Write the string and update the buffer pointer.\r
315                     //\r
316                     strncpy(pcBuf, pcStr, ulIdx);\r
317                     pcBuf += ulIdx;\r
318 \r
319                     //\r
320                     // Decrement the buffer size limit.\r
321                     //\r
322                     ulSize -= ulIdx;\r
323 \r
324                     //\r
325                     //\r
326                     // This command has been handled.\r
327                     //\r
328                     break;\r
329                 }\r
330 \r
331                 //\r
332                 // Handle the %u command.\r
333                 //\r
334                 case 'u':\r
335                 {\r
336                     //\r
337                     // Get the value from the varargs.\r
338                     //\r
339                     ulValue = va_arg(vaArgP, unsigned long);\r
340 \r
341                     //\r
342                     // Reset the buffer position.\r
343                     //\r
344                     ulPos = 0;\r
345 \r
346                     //\r
347                     // Set the base to 10.\r
348                     //\r
349                     ulBase = 10;\r
350 \r
351                     //\r
352                     // Convert the value to ASCII.\r
353                     //\r
354                     goto convert;\r
355                 }\r
356 \r
357                 //\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
361                 //\r
362                 case 'x':\r
363                 case 'X':\r
364                 {\r
365                     //\r
366                     // Get the value from the varargs.\r
367                     //\r
368                     ulValue = va_arg(vaArgP, unsigned long);\r
369 \r
370                     //\r
371                     // Reset the buffer position.\r
372                     //\r
373                     ulPos = 0;\r
374 \r
375                     //\r
376                     // Set the base to 16.\r
377                     //\r
378                     ulBase = 16;\r
379 \r
380                     //\r
381                     // Determine the number of digits in the string version of\r
382                     // the value.\r
383                     //\r
384 convert:\r
385                     for(ulIdx = 1;\r
386                         (((ulIdx * ulBase) <= ulValue) &&\r
387                          (((ulIdx * ulBase) / ulBase) == ulIdx));\r
388                         ulIdx *= ulBase, ulCount--)\r
389                     {\r
390                     }\r
391 \r
392                     //\r
393                     // Provide additional padding at the beginning of the\r
394                     // string conversion if needed.\r
395                     //\r
396                     if((ulCount > 1) && (ulCount < 16))\r
397                     {\r
398                         for(ulCount--; ulCount; ulCount--)\r
399                         {\r
400                             *pcBuf++ = cFill;\r
401                             ulPos++;\r
402 \r
403                             //\r
404                             // Decrement buffer size and check to see if\r
405                             // buffer limit is reached.\r
406                             //\r
407                             ulSize--;\r
408                             if(ulSize == 0)\r
409                             {\r
410                                 break;\r
411                             }\r
412                         }\r
413                     }\r
414 \r
415                     //\r
416                     // Convert the value into a string.\r
417                     //\r
418                     for(; ulIdx; ulIdx /= ulBase)\r
419                     {\r
420                         *pcBuf++ = g_pcHex[(ulValue / ulIdx) % ulBase];\r
421                         ulPos++;\r
422 \r
423                         //\r
424                         // Decrement buffer size and check to see if\r
425                         // buffer limit is reached.\r
426                         //\r
427                         ulSize--;\r
428                         if(ulSize == 0)\r
429                         {\r
430                             break;\r
431                         }\r
432                     }\r
433 \r
434                     //\r
435                     // This command has been handled.\r
436                     //\r
437                     break;\r
438                 }\r
439 \r
440                 //\r
441                 // Handle the %% command.\r
442                 //\r
443                 case '%':\r
444                 {\r
445                     //\r
446                     // Simply write a single %.\r
447                     //\r
448                     *pcBuf++ = pcString[-1];\r
449                     ulSize--;\r
450 \r
451                     //\r
452                     // This command has been handled.\r
453                     //\r
454                     break;\r
455                 }\r
456 \r
457                 //\r
458                 // Handle all other commands.\r
459                 //\r
460                 default:\r
461                 {\r
462                     //\r
463                     // Indicate an error.\r
464                     //\r
465                     if(ulSize > 5)\r
466                     {\r
467                         strncpy(pcBuf, "ERROR", 5);\r
468                         pcBuf += 5;\r
469                         ulSize -= 5;\r
470                     }\r
471 \r
472                     //\r
473                     // This command has been handled.\r
474                     //\r
475                     break;\r
476                 }\r
477             }\r
478         }\r
479     }\r
480 \r
481     //\r
482     // Null terminate the string in the buffer.\r
483     //\r
484     *pcBuf = 0;\r
485         return ( int ) pcBuf - ( int ) pcOriginalBuf;\r
486 }\r
487 \r
488 //*****************************************************************************\r
489 //\r
490 //! A simple sprintf function supporting \%c, \%d, \%s, \%u, \%x, and \%X.\r
491 //!\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
495 //! format string.\r
496 //!\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
499 //!\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
508 //!\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
516 //!\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
520 //!\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
523 //!\r
524 //! \return None.\r
525 //\r
526 //*****************************************************************************\r
527 void\r
528 usprintf(char *pcBuf, const char *pcString, ...)\r
529 {\r
530     va_list vaArgP;\r
531 \r
532     //\r
533     // Start the varargs processing.\r
534     //\r
535     va_start(vaArgP, pcString);\r
536 \r
537     //\r
538     // Call vsnprintf to perform the conversion.  Use a\r
539     // large number for the buffer size.\r
540     //\r
541     uvsnprintf(pcBuf, 0xffff, pcString, vaArgP);\r
542 \r
543     //\r
544     // End the varargs processing.\r
545     //\r
546     va_end(vaArgP);\r
547 }\r
548 \r
549 //*****************************************************************************\r
550 //\r
551 //! A simple snprintf function supporting \%c, \%d, \%s, \%u, \%x, and \%X.\r
552 //!\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
557 //! format string.\r
558 //!\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
561 //!\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
570 //!\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
578 //!\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
582 //!\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
586 //!\r
587 //! \return None.\r
588 //\r
589 //*****************************************************************************\r
590 int\r
591 usnprintf(char *pcBuf, unsigned long ulSize, const char *pcString, ...)\r
592 {\r
593 int iReturn;\r
594 \r
595     va_list vaArgP;\r
596 \r
597     //\r
598     // Start the varargs processing.\r
599     //\r
600     va_start(vaArgP, pcString);\r
601 \r
602     //\r
603     // Call vsnprintf to perform the conversion.\r
604     //\r
605     iReturn = uvsnprintf(pcBuf, ulSize, pcString, vaArgP);\r
606 \r
607     //\r
608     // End the varargs processing.\r
609     //\r
610     va_end(vaArgP);\r
611 \r
612         return iReturn;\r
613 }\r
614 \r
615 //*****************************************************************************\r
616 //\r
617 // Close the Doxygen group.\r
618 //! @}\r
619 //\r
620 //*****************************************************************************\r