OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [drivers/] [LuminaryMicro/] [ustdlib.c] - Blame information for rev 636

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 610 jeremybenn
//*****************************************************************************
2
//
3
// ustdlib.c - Simple standard library functions.
4
//
5
// Copyright (c) 2007 Luminary Micro, Inc.  All rights reserved.
6
//
7
// Software License Agreement
8
//
9
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
10
// exclusively on LMI's microcontroller products.
11
//
12
// The software is owned by LMI and/or its suppliers, and is protected under
13
// applicable copyright laws.  All rights are reserved.  Any use in violation
14
// of the foregoing restrictions may subject the user to criminal sanctions
15
// under applicable laws, as well as to civil liability for the breach of the
16
// terms and conditions of this license.
17
//
18
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
19
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
20
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
21
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
22
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
23
//
24
//*****************************************************************************
25
 
26
#include <stdarg.h>
27
#include <string.h>
28
#include "debug.h"
29
 
30
//*****************************************************************************
31
//
32
//! \addtogroup utilities_api
33
//! @{
34
//
35
//*****************************************************************************
36
 
37
//*****************************************************************************
38
//
39
// A mapping from an integer between 0 and 15 to its ASCII character
40
// equivalent.
41
//
42
//*****************************************************************************
43
static const char * const g_pcHex = "0123456789abcdef";
44
 
45
//*****************************************************************************
46
//
47
//! A simple vsnprintf function supporting \%c, \%d, \%s, \%u, \%x, and \%X.
48
//!
49
//! \param pcBuf points to the buffer where the converted string is stored.
50
//! \param ulSize is the size of the buffer.
51
//! \param pcString is the format string.
52
//! \param vaArgP is the list of optional arguments, which depend on the
53
//! contents of the format string.
54
//!
55
//! This function is very similar to the C library <tt>vsnprintf()</tt>
56
//! function. Only the following formatting characters are supported:
57
//!
58
//! - \%c to print a character
59
//! - \%d to print a decimal value
60
//! - \%s to print a string
61
//! - \%u to print an unsigned decimal value
62
//! - \%x to print a hexadecimal value using lower case letters
63
//! - \%X to print a hexadecimal value using lower case letters (not upper case
64
//! letters as would typically be used)
65
//! - \%\% to print out a \% character
66
//!
67
//! For \%d, \%u, \%x, and \%X, an optional number may reside between the \%
68
//! and the format character, which specifies the minimum number of characters
69
//! to use for that value; if preceeded by a 0 then the extra characters will
70
//! be filled with zeros instead of spaces.  For example, ``\%8d'' will use
71
//! eight characters to print the decimal value with spaces added to reach
72
//! eight; ``\%08d'' will use eight characters as well but will add zeros
73
//! instead of spaces.
74
//!
75
//! The type of the arguments after \b pcString must match the requirements of
76
//! the format string.  For example, if an integer was passed where a string
77
//! was expected, an error of some kind will most likely occur.
78
//!
79
//! The \b ulSize parameter limits the number of characters that will be
80
//! stored in the buffer pointed to by \b pcBuf to prevent the possibility
81
//! of a buffer overflow.  The buffer size should be large enough to hold
82
//! the expected converted output string, including the null termination
83
//! character.
84
//!
85
//! The function will return the number of characters that would be
86
//! converted as if there were no limit on the buffer size.  Therefore
87
//! it is possible for the function to return a count that is greater than
88
//! the specified buffer size.  If this happens, it means that the output
89
//! was truncated.
90
//!
91
//! \return the number of characters that were to be stored, not including
92
//! the NULL termination character, regardless of space in the buffer.
93
//
94
//*****************************************************************************
95
int
96
uvsnprintf(char *pcBuf, unsigned long ulSize, const char *pcString,
97
           va_list vaArgP)
98
{
99
    unsigned long ulIdx, ulValue, ulCount, ulBase;
100
    char *pcStr, cFill;
101
    int iConvertCount = 0;
102
 
103
    //
104
    // Check the arguments.
105
    //
106
    ASSERT(pcString != 0);
107
    ASSERT(pcBuf != 0);
108
    ASSERT(ulSize != 0);
109
 
110
    //
111
    // Adjust buffer size limit to allow one space for null termination.
112
    //
113
    if(ulSize)
114
    {
115
        ulSize--;
116
    }
117
 
118
    //
119
    // Initialize the count of characters converted.
120
    //
121
    iConvertCount = 0;
122
 
123
    //
124
    // Loop while there are more characters in the format string.
125
    //
126
    while(*pcString)
127
    {
128
        //
129
        // Find the first non-% character, or the end of the string.
130
        //
131
        for(ulIdx = 0; (pcString[ulIdx] != '%') && (pcString[ulIdx] != '\0');
132
            ulIdx++)
133
        {
134
        }
135
 
136
        //
137
        // Write this portion of the string to the output buffer.  If
138
        // there are more characters to write than there is space in the
139
        // buffer, then only write as much as will fit in the buffer.
140
        //
141
        if(ulIdx > ulSize)
142
        {
143
            strncpy(pcBuf, pcString, ulSize);
144
            pcBuf += ulSize;
145
            ulSize = 0;
146
        }
147
        else
148
        {
149
            strncpy(pcBuf, pcString, ulIdx);
150
            pcBuf += ulIdx;
151
            ulSize -= ulIdx;
152
        }
153
 
154
        //
155
        // Update the conversion count.  This will be the number of
156
        // characters that should have been written, even if there was
157
        // not room in the buffer.
158
        //
159
        iConvertCount += ulIdx;
160
 
161
        //
162
        // Skip the portion of the format string that was written.
163
        //
164
        pcString += ulIdx;
165
 
166
        //
167
        // See if the next character is a %.
168
        //
169
        if(*pcString == '%')
170
        {
171
            //
172
            // Skip the %.
173
            //
174
            pcString++;
175
 
176
            //
177
            // Set the digit count to zero, and the fill character to space
178
            // (i.e. to the defaults).
179
            //
180
            ulCount = 0;
181
            cFill = ' ';
182
 
183
            //
184
            // It may be necessary to get back here to process more characters.
185
            // Goto's aren't pretty, but effective.  I feel extremely dirty for
186
            // using not one but two of the beasts.
187
            //
188
again:
189
 
190
            //
191
            // Determine how to handle the next character.
192
            //
193
            switch(*pcString++)
194
            {
195
                //
196
                // Handle the digit characters.
197
                //
198
                case '0':
199
                case '1':
200
                case '2':
201
                case '3':
202
                case '4':
203
                case '5':
204
                case '6':
205
                case '7':
206
                case '8':
207
                case '9':
208
                {
209
                    //
210
                    // If this is a zero, and it is the first digit, then the
211
                    // fill character is a zero instead of a space.
212
                    //
213
                    if((pcString[-1] == '0') && (ulCount == 0))
214
                    {
215
                        cFill = '0';
216
                    }
217
 
218
                    //
219
                    // Update the digit count.
220
                    //
221
                    ulCount *= 10;
222
                    ulCount += pcString[-1] - '0';
223
 
224
                    //
225
                    // Get the next character.
226
                    //
227
                    goto again;
228
                }
229
 
230
                //
231
                // Handle the %c command.
232
                //
233
                case 'c':
234
                {
235
                    //
236
                    // Get the value from the varargs.
237
                    //
238
                    ulValue = va_arg(vaArgP, unsigned long);
239
 
240
                    //
241
                    // Copy the character to the output buffer, if
242
                    // there is room.  Update the buffer size remaining.
243
                    //
244
                    if(ulSize != 0)
245
                    {
246
                        *pcBuf++ = (char)ulValue;
247
                        ulSize--;
248
                    }
249
 
250
                    //
251
                    // Update the conversion count.
252
                    //
253
                    iConvertCount++;
254
 
255
                    //
256
                    // This command has been handled.
257
                    //
258
                    break;
259
                }
260
 
261
                //
262
                // Handle the %d command.
263
                //
264
                case 'd':
265
                {
266
                    //
267
                    // Get the value from the varargs.
268
                    //
269
                    ulValue = va_arg(vaArgP, unsigned long);
270
 
271
                    //
272
                    // If the value is negative, make it positive and stick a
273
                    // minus sign in the beginning of the buffer.
274
                    //
275
                    if((long)ulValue < 0)
276
                    {
277
                        ulValue = -(long)ulValue;
278
 
279
                        if(ulSize != 0)
280
                        {
281
                            *pcBuf++ = '-';
282
                            ulSize--;
283
                        }
284
 
285
                        //
286
                        // Update the conversion count.
287
                        //
288
                        iConvertCount++;
289
                    }
290
 
291
                    //
292
                    // Set the base to 10.
293
                    //
294
                    ulBase = 10;
295
 
296
                    //
297
                    // Convert the value to ASCII.
298
                    //
299
                    goto convert;
300
                }
301
 
302
                //
303
                // Handle the %s command.
304
                //
305
                case 's':
306
                {
307
                    //
308
                    // Get the string pointer from the varargs.
309
                    //
310
                    pcStr = va_arg(vaArgP, char *);
311
 
312
                    //
313
                    // Determine the length of the string.
314
                    //
315
                    for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++)
316
                    {
317
                    }
318
 
319
                    //
320
                    // Copy the string to the output buffer.  Only copy
321
                    // as much as will fit in the buffer.  Update the
322
                    // output buffer pointer and the space remaining.
323
                    //
324
                    if(ulIdx > ulSize)
325
                    {
326
                        strncpy(pcBuf, pcStr, ulSize);
327
                        pcBuf += ulSize;
328
                        ulSize = 0;
329
                    }
330
                    else
331
                    {
332
                        strncpy(pcBuf, pcStr, ulIdx);
333
                        pcBuf += ulIdx;
334
                        ulSize -= ulIdx;
335
                    }
336
 
337
                    //
338
                    // Update the conversion count.  This will be the number of
339
                    // characters that should have been written, even if there
340
                    // was not room in the buffer.
341
                    //
342
                    iConvertCount += ulIdx;
343
 
344
                    //
345
                    //
346
                    // This command has been handled.
347
                    //
348
                    break;
349
                }
350
 
351
                //
352
                // Handle the %u command.
353
                //
354
                case 'u':
355
                {
356
                    //
357
                    // Get the value from the varargs.
358
                    //
359
                    ulValue = va_arg(vaArgP, unsigned long);
360
 
361
                    //
362
                    // Set the base to 10.
363
                    //
364
                    ulBase = 10;
365
 
366
                    //
367
                    // Convert the value to ASCII.
368
                    //
369
                    goto convert;
370
                }
371
 
372
                //
373
                // Handle the %x and %X commands.  Note that they are treated
374
                // identically; i.e. %X will use lower case letters for a-f
375
                // instead of the upper case letters is should use.
376
                //
377
                case 'x':
378
                case 'X':
379
                {
380
                    //
381
                    // Get the value from the varargs.
382
                    //
383
                    ulValue = va_arg(vaArgP, unsigned long);
384
 
385
                    //
386
                    // Set the base to 16.
387
                    //
388
                    ulBase = 16;
389
 
390
                    //
391
                    // Determine the number of digits in the string version of
392
                    // the value.
393
                    //
394
convert:
395
                    for(ulIdx = 1;
396
                        (((ulIdx * ulBase) <= ulValue) &&
397
                         (((ulIdx * ulBase) / ulBase) == ulIdx));
398
                        ulIdx *= ulBase, ulCount--)
399
                    {
400
                    }
401
 
402
                    //
403
                    // Provide additional padding at the beginning of the
404
                    // string conversion if needed.
405
                    //
406
                    if((ulCount > 1) && (ulCount < 16))
407
                    {
408
                        for(ulCount--; ulCount; ulCount--)
409
                        {
410
                            //
411
                            // Copy the character to the output buffer if
412
                            // there is room.
413
                            //
414
                            if(ulSize != 0)
415
                            {
416
                                *pcBuf++ = cFill;
417
                                ulSize--;
418
                            }
419
 
420
                            //
421
                            // Update the conversion count.
422
                            //
423
                            iConvertCount++;
424
                        }
425
                    }
426
 
427
                    //
428
                    // Convert the value into a string.
429
                    //
430
                    for(; ulIdx; ulIdx /= ulBase)
431
                    {
432
                        //
433
                        // Copy the character to the output buffer if
434
                        // there is room.
435
                        //
436
                        if(ulSize != 0)
437
                        {
438
                            *pcBuf++ = g_pcHex[(ulValue / ulIdx) % ulBase];
439
                            ulSize--;
440
                        }
441
 
442
                        //
443
                        // Update the conversion count.
444
                        //
445
                        iConvertCount++;
446
                    }
447
 
448
                    //
449
                    // This command has been handled.
450
                    //
451
                    break;
452
                }
453
 
454
                //
455
                // Handle the %% command.
456
                //
457
                case '%':
458
                {
459
                    //
460
                    // Simply write a single %.
461
                    //
462
                    if(ulSize != 0)
463
                    {
464
                        *pcBuf++ = pcString[-1];
465
                        ulSize--;
466
                    }
467
 
468
                    //
469
                    // Update the conversion count.
470
                    //
471
                    iConvertCount++;
472
 
473
                    //
474
                    // This command has been handled.
475
                    //
476
                    break;
477
                }
478
 
479
                //
480
                // Handle all other commands.
481
                //
482
                default:
483
                {
484
                    //
485
                    // Indicate an error.
486
                    //
487
                    if(ulSize >= 5)
488
                    {
489
                        strncpy(pcBuf, "ERROR", 5);
490
                        pcBuf += 5;
491
                        ulSize -= 5;
492
                    }
493
                    else
494
                    {
495
                        strncpy(pcBuf, "ERROR", ulSize);
496
                        pcBuf += ulSize;
497
                        ulSize = 0;
498
                    }
499
 
500
                    //
501
                    // Update the conversion count.
502
                    //
503
                    iConvertCount += 5;
504
 
505
                    //
506
                    // This command has been handled.
507
                    //
508
                    break;
509
                }
510
            }
511
        }
512
    }
513
 
514
    //
515
    // Null terminate the string in the buffer.
516
    //
517
    *pcBuf = 0;
518
    return(iConvertCount);
519
}
520
 
521
//*****************************************************************************
522
//
523
//! A simple sprintf function supporting \%c, \%d, \%s, \%u, \%x, and \%X.
524
//!
525
//! \param pcBuf is the buffer where the converted string is stored.
526
//! \param pcString is the format string.
527
//! \param ... are the optional arguments, which depend on the contents of the
528
//! format string.
529
//!
530
//! This function is very similar to the C library <tt>sprintf()</tt> function.
531
//! Only the following formatting characters are supported:
532
//!
533
//! - \%c to print a character
534
//! - \%d to print a decimal value
535
//! - \%s to print a string
536
//! - \%u to print an unsigned decimal value
537
//! - \%x to print a hexadecimal value using lower case letters
538
//! - \%X to print a hexadecimal value using lower case letters (not upper case
539
//! letters as would typically be used)
540
//! - \%\% to print out a \% character
541
//!
542
//! For \%d, \%u, \%x, and \%X, an optional number may reside between the \%
543
//! and the format character, which specifies the minimum number of characters
544
//! to use for that value; if preceeded by a 0 then the extra characters will
545
//! be filled with zeros instead of spaces.  For example, ``\%8d'' will use
546
//! eight characters to print the decimal value with spaces added to reach
547
//! eight; ``\%08d'' will use eight characters as well but will add zeros
548
//! instead of spaces.
549
//!
550
//! The type of the arguments after \b pcString must match the requirements of
551
//! the format string.  For example, if an integer was passed where a string
552
//! was expected, an error of some kind will most likely occur.
553
//!
554
//! The caller must ensure that the buffer pcBuf is large enough to hold the
555
//! entire converted string, including the null termination character.
556
//!
557
//! \return The count of characters that were written to the output buffer,
558
//! not including the NULL termination character.
559
//
560
//*****************************************************************************
561
int
562
usprintf(char *pcBuf, const char *pcString, ...)
563
{
564
    va_list vaArgP;
565
    int iRet;
566
 
567
    //
568
    // Start the varargs processing.
569
    //
570
    va_start(vaArgP, pcString);
571
 
572
    //
573
    // Call vsnprintf to perform the conversion.  Use a
574
    // large number for the buffer size.
575
    //
576
    iRet = uvsnprintf(pcBuf, 0xffff, pcString, vaArgP);
577
 
578
    //
579
    // End the varargs processing.
580
    //
581
    va_end(vaArgP);
582
 
583
    //
584
    // Return the conversion count.
585
    //
586
    return(iRet);
587
}
588
 
589
//*****************************************************************************
590
//
591
//! A simple snprintf function supporting \%c, \%d, \%s, \%u, \%x, and \%X.
592
//!
593
//! \param pcBuf is the buffer where the converted string is stored.
594
//! \param ulSize is the size of the buffer.
595
//! \param pcString is the format string.
596
//! \param ... are the optional arguments, which depend on the contents of the
597
//! format string.
598
//!
599
//! This function is very similar to the C library <tt>sprintf()</tt> function.
600
//! Only the following formatting characters are supported:
601
//!
602
//! - \%c to print a character
603
//! - \%d to print a decimal value
604
//! - \%s to print a string
605
//! - \%u to print an unsigned decimal value
606
//! - \%x to print a hexadecimal value using lower case letters
607
//! - \%X to print a hexadecimal value using lower case letters (not upper case
608
//! letters as would typically be used)
609
//! - \%\% to print out a \% character
610
//!
611
//! For \%d, \%u, \%x, and \%X, an optional number may reside between the \%
612
//! and the format character, which specifies the minimum number of characters
613
//! to use for that value; if preceeded by a 0 then the extra characters will
614
//! be filled with zeros instead of spaces.  For example, ``\%8d'' will use
615
//! eight characters to print the decimal value with spaces added to reach
616
//! eight; ``\%08d'' will use eight characters as well but will add zeros
617
//! instead of spaces.
618
//!
619
//! The type of the arguments after \b pcString must match the requirements of
620
//! the format string.  For example, if an integer was passed where a string
621
//! was expected, an error of some kind will most likely occur.
622
//!
623
//! The function will copy at most \b ulSize - 1 characters into the
624
//! buffer \b pcBuf.  One space is reserved in the buffer for the null
625
//! termination character.
626
//!
627
//! The function will return the number of characters that would be
628
//! converted as if there were no limit on the buffer size.  Therefore
629
//! it is possible for the function to return a count that is greater than
630
//! the specified buffer size.  If this happens, it means that the output
631
//! was truncated.
632
//!
633
//! \return the number of characters that were to be stored, not including
634
//! the NULL termination character, regardless of space in the buffer.
635
//
636
//*****************************************************************************
637
int
638
usnprintf(char *pcBuf, unsigned long ulSize, const char *pcString, ...)
639
{
640
int iRet;
641
 
642
    va_list vaArgP;
643
 
644
    //
645
    // Start the varargs processing.
646
    //
647
    va_start(vaArgP, pcString);
648
 
649
    //
650
    // Call vsnprintf to perform the conversion.
651
    //
652
    iRet = uvsnprintf(pcBuf, ulSize, pcString, vaArgP);
653
 
654
    //
655
    // End the varargs processing.
656
    //
657
    va_end(vaArgP);
658
 
659
    //
660
    // Return the conversion count.
661
    //
662
    return(iRet);
663
}
664
 
665
//*****************************************************************************
666
//
667
// Close the Doxygen group.
668
//! @}
669
//
670
//*****************************************************************************

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.