source: soft/giet_vm/giet_libs/stdlib.c @ 771

Last change on this file since 771 was 771, checked in by alain, 9 years ago

Introducing the generic xprintf() function, called by the various *printf() functions.

File size: 11.0 KB
RevLine 
[259]1//////////////////////////////////////////////////////////////////////////////////
2// File     : stdlib.c
3// Date     : 05/12/2013
4// Author   : Clément DEVIGNE
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
[271]8#include <stdlib.h>
[771]9#include <stdio.h>
10#include <stdarg.h>
[271]11
[647]12/////////////////////////
[580]13int atoi(const char *str)
[259]14{
15    int res  = 0; // Initialize result
16    int sign = 1; // Initialize sign as positive
17    int i    = 0; // Initialize index of first digit
18
19    if (str[0] == '-') //If number is negative, then update sign
20    {
21        sign = -1; 
22        i++;           // Also update index of first digit
23    }
24
25    for (; str[i] != '\0'; ++i) // Iterate through all digits and update the result
26    {
27        res = res*10 + str[i] - '0';
28    }
29
30    // Return result with sign
31    return sign*res;
32}
[580]33
[647]34////////////////////////////
[580]35double atof(const char *str)
36{
37    const char *pstr = str;
38    double res = 0;
39    double exp = 0.1;
40    short sign = 1;
41    short dec = 0;
42
43    while (*pstr != '\0')
44    {
45        if (*pstr == '-')
46        {
47            if (str != pstr) break;
48            sign = -1;
49        }
[259]50       
[580]51        else if (*pstr == '.')
52        {
53            if (dec) break;
54            dec = 1;
55        }
56       
57        else if (*pstr >= '0' && *pstr <= '9')
58        {
59            if (dec)
60            {
61                res = res + ((*pstr - '0')*exp);
62                exp = exp / 10;
63            }
64            else
65            {
66                res = (res * 10) + (*pstr - '0');
67            }
68        }
69       
70        else
71        {
72            break;
73        }
74        pstr++;
75    }
76    return sign * res;
77}
78
[647]79///////////////////////////////////////////////////////////////
[382]80void * memcpy(void *_dst, const void * _src, unsigned int size) 
[352]81{
[271]82    unsigned int * dst = _dst;
83    const unsigned int * src = _src;
84    if (!((unsigned int) dst & 3) && !((unsigned int) src & 3) )
[352]85    {
86        while (size > 3) 
87        {
[271]88            *dst++ = *src++;
89            size -= 4;
90        }
[352]91    }
[271]92
93    unsigned char *cdst = (unsigned char*)dst;
94    unsigned char *csrc = (unsigned char*)src;
95
[352]96    while (size--) 
97    {
[271]98        *cdst++ = *csrc++;
99    }
100    return _dst;
101}
102
[647]103//////////////////////////////////////////////////////////
[382]104inline void * memset(void * dst, int s, unsigned int size) 
[352]105{
[271]106    char * a = (char *) dst;
[382]107    while (size--)
[352]108    {
[271]109        *a++ = (char)s;
110    }
111    return dst;
112}
113
[647]114///////////////////////////////////
115unsigned int strlen( char* string )
116{
117    unsigned int i = 0;
118    while ( string[i] != 0 ) i++;
119    return i;
120}
121
122///////////////////////////////
123unsigned int strcmp( char * s1,
124                     char * s2 )
125{
126    while (1)
127    {
128        if (*s1 != *s2) return 1;
129        if (*s1 == 0)   break;
130        s1++, s2++;
131    }
132    return 0;
133}
134
135/////////////////////////
136char* strcpy( char* dest, 
137              char* source )
138{
139    if (!dest || !source) return dest;
140
141    while (*source)
142    {
143        *(dest) = *(source);
144        dest++;
145        source++;
146    }
147    *dest = 0;
148    return dest;
149}
150
[771]151
152//////////////////////////////////////////
153unsigned int xprintf( char*        string,
154                      unsigned int length,
155                      char*        format, 
156                      va_list*     args ) 
157{
158    unsigned int ps = 0;    // write pointer to the string buffer
159
160#define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
161
162xprintf_text:
163
164    while ( *format != 0 ) 
165    {
166
167        if (*format == '%')   // copy argument to string
168        {
169            format++;
170            goto xprintf_arguments;
171        }
172        else                  // copy one char to string
173        {
174            TO_STREAM( *format );
175            format++;
176        }
177    }
178
179    return ps;
180
181xprintf_arguments:
182
183    {
184        char              buf[30];    // buffer to display one number
185        char *            pbuf;       // pointer on first char to display
186        unsigned int      len = 0;    // number of char to display
187        static const char HexaTab[] = "0123456789ABCDEF";
188        unsigned int      i;
189       
190        // Ignore fields width and precision
191        for ( ; *format >= '0' && *format <= '9'; format++ );
192
193        switch (*format) 
194        {
195            case ('c'):             // char conversion
196            {
197                int val = va_arg( *args, int );
198                buf[0] = val;
199                pbuf   = buf;
200                len    = 1;
201                break;
202            }
203            case ('d'):             // decimal signed integer
204            {
205                int val = va_arg( *args, int );
206                if (val < 0) 
207                {
208                    TO_STREAM( '-' );
209                    val = -val;
210                }
211                for(i = 0; i < 10; i++) 
212                {
213
214                    buf[9 - i] = HexaTab[val % 10];
215                    if (!(val /= 10)) break;
216                }
217                len =  i + 1;
218                pbuf = &buf[9 - i];
219                break;
220            }
221            case ('u'):             // decimal unsigned integer
222            {
223                unsigned int val = va_arg( *args, unsigned int );
224                for(i = 0; i < 10; i++) 
225                {
226                    buf[9 - i] = HexaTab[val % 10];
227                    if (!(val /= 10)) break;
228                }
229                len =  i + 1;
230                pbuf = &buf[9 - i];
231                break;
232            }
233            case ('x'):             // 32 bits hexadecimal
234            case ('l'):             // 64 bits hexadecimal
235            {
236                unsigned int       imax;
237                unsigned long long val;
238               
239                if ( *format == 'l' )   // 64 bits
240                {
241                    val = va_arg( *args, unsigned long long);
242                    imax = 16;
243                }
244                else                    // 32 bits
245                {
246                    val = va_arg( *args, unsigned int);
247                    imax = 8;
248                }
249               
250                TO_STREAM( '0' );
251                TO_STREAM( 'x' );
252               
253                for(i = 0; i < imax; i++) 
254                {
255                    buf[(imax-1) - i] = HexaTab[val % 16];
256                    if (!(val /= 16))  break;
257                }
258                len =  i + 1;
259                pbuf = &buf[(imax-1) - i];
260                break;
261            }
262            case ('s'):             /* string */
263            {
264                char* str = va_arg( *args, char* );
265                while (str[len]) { len++; }
266                pbuf = str;
267                break;
268            }
269            case ('e'):
270            case ('f'):
271            case ('g'):             // IEEE754 64 bits
272            {
273                union
274                {
275                    double d;
276                    unsigned long long ull;
277                } val;
278               
279                val.d = va_arg( *args, double );
280               
281                unsigned long long digits;
282                digits = val.ull & 0xFFFFFFFFFFFFFULL;    // mantisse
283               
284                unsigned int base;
285                base = (unsigned int)((val.ull & 0x7FF0000000000000ULL) >> 52); // exp
286
287                unsigned int intp;
288                intp = (unsigned int)val.d;         // integer part
289
290                unsigned int decp;                  // decimal part
291               
292                int isvalue = 0;
293               
294                if (base == 0x7FF) // special values
295                {
296                    if (digits & 0xFFFFFFFFFFFFFULL)  // Not a Number
297                    {
298                        buf[0] = 'N';
299                        buf[1] = 'a';
300                        buf[2] = 'N';
301                        len = 3;
302                        pbuf = buf;
303                    }
304                    else                              // infinite
305                    {
306                        /* inf */
307                        buf[0] = (val.ull & 0x8000000000000000ULL) ? '-' : '+';
308                        buf[1] = 'i';
309                        buf[2] = 'n';
310                        buf[3] = 'f';
311                        len = 4;
312                        pbuf = buf;
313                    }
314                    break;
315                }
316               
317                if (val.ull & 0x8000000000000000ULL)  // negative
318                {
319                    TO_STREAM( '-' );
320                    val.d = val.d * -1;
321                }
322                else                                  // positive
323                {
324                    TO_STREAM( '+' );
325                }
326               
327                if (val.d > 0xFFFFFFFF)              // overflow
328                {
329                    buf[0] = 'B';
330                    buf[1] = 'I';
331                    buf[2] = 'G';
332                    len = 3;
333                    pbuf = buf;
334                    break;
335                }
336               
337                val.d -= (double)intp;
338                decp = (unsigned int)(val.d * 1000000000);
339               
340                for(i = 0; i < 10; i++) 
341                {
342                    if ((!isvalue) && (intp % 10)) isvalue = 1;
343                    buf[9 - i] = HexaTab[intp % 10];
344                    if (!(intp /= 10)) break;
345                }
346                pbuf = &buf[9 - i];
347                len = i+11;
348                buf[10] = '.';
349               
350                for(i = 0; i < 9; i++)
351                {
352                    if ((!isvalue) && (decp % 10)) isvalue = 1;
353                    buf[19 - i] = HexaTab[decp % 10];
354                    decp /= 10;
355                }
356               
357                if (!isvalue)
358                {
359                    if (val.d != 0)                   // underflow
360                    {
361                        buf[0] = 'T';
362                        buf[1] = 'I';
363                        buf[2] = 'N';
364                        buf[3] = 'Y';
365                        len = 4;
366                        pbuf = buf;
367                    }
368                }
369
370                break;
371            }
372                   
373            default:       // unsupported argument type
374            {
375                return -1;
376            }
377        }  // end switch on  argument type
378
379        format++;
380
381        // copy argument to string
382        for( i = 0 ; i < len ; i++ )
383        {
384            TO_STREAM( pbuf[i] );
385        }
386       
387        goto xprintf_text;
388    }
389} // end xprintf()
390
391///////////////////////////////////////////
392unsigned int snprintf( char*        string,
393                       unsigned int length,
394                       char*        format, ... )
395{
396    va_list      args;
397    unsigned int count;
398
399    va_start( args, format );
400    count = xprintf( string , length , format , &args ); 
401    va_end( args );
402
403    if ( count == 0xFFFFFFFF ) giet_pthread_exit("error in snprintf()");
404    else string[count] = 0;
405
406    return count;
407}
[259]408// Local Variables:
409// tab-width: 4
410// c-basic-offset: 4
411// c-file-offsets:((innamespace . 0)(inline-open . 0))
412// indent-tabs-mode: nil
413// End:
414// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.