source: trunk/libs/stdlib.c @ 428

Last change on this file since 428 was 426, checked in by alain, 7 years ago

The "nostdio" library has been integrated in the stdio library.

File size: 14.5 KB
Line 
1/*
2 * stdlib.c - User level C library implementation.
3 *
4 * Author     Alain Greiner (2016,2017)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <stdio.h>
25#include <stdarg.h>
26#include <pthread.h>
27#include <stdlib.h>
28
29/////////////////////////////
30void assert( int expression ) 
31{
32    if( expression == 0 )
33    {
34        printf("\n[ASSERT FAILED] in %s at line %d in file %s\n",
35        __FUNCTION__ , __LINE__ , __FILE__ );
36
37        exit( 0 );
38    }
39}
40
41//////////////////////////
42int atoi(const char * str)
43{
44    int res  = 0;      // Initialize result
45    int sign = 1;      // Initialize sign as positive
46    int i    = 0;      // Initialize index of first digit
47
48    if( (str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X')) )   // hexa
49    {
50        i = 2;
51
52        while( str[i] != 0 )
53        {
54            if     ( (str[i] >= '0') && (str[i] <= '9') ) res = (res<<4) + (str[i] - '0');
55            else if( (str[i] >= 'A') && (str[i] <= 'F') ) res = (res<<4) + (str[i] - 'A');
56            else if( (str[i] >= 'a') && (str[i] <= 'f') ) res = (res<<4) + (str[i] - 'a');
57            else return 0;
58            i++;
59        }
60    }
61    else                                                            // decimal
62    {
63        if (str[0] == '-')  //  number is negative, update sign
64        {
65            sign = -1; 
66            i++;           // Also update index of first digit
67        }
68
69        while( str[i] != 0 )
70        {
71            if( (str[i] >= '0') && (str[i] <= '9') ) res = (res*10) + (str[i] - '0');
72            else return 0;
73            i++;
74        }
75    }
76
77    // Return result with sign
78    return sign*res;
79}
80
81////////////////////////////
82double atof(const char *str)
83{
84    const char *pstr = str;
85    double res = 0;
86    double exp = 0.1;
87    short sign = 1;
88    short dec = 0;
89
90    while (*pstr != '\0')
91    {
92        if (*pstr == '-')
93        {
94            if (str != pstr) break;
95            sign = -1;
96        }
97       
98        else if (*pstr == '.')
99        {
100            if (dec) break;
101            dec = 1;
102        }
103       
104        else if (*pstr >= '0' && *pstr <= '9')
105        {
106            if (dec)
107            {
108                res = res + ((*pstr - '0')*exp);
109                exp = exp / 10;
110            }
111            else
112            {
113                res = (res * 10) + (*pstr - '0');
114            }
115        }
116       
117        else
118        {
119            break;
120        }
121        pstr++;
122    }
123    return sign * res;
124}
125
126///////////////////////////////////////////////////////////////
127void * memcpy(void *_dst, const void * _src, unsigned int size) 
128{
129    unsigned int * dst = _dst;
130    const unsigned int * src = _src;
131    if (!((unsigned int) dst & 3) && !((unsigned int) src & 3) )
132    {
133        while (size > 3) 
134        {
135            *dst++ = *src++;
136            size -= 4;
137        }
138    }
139
140    unsigned char *cdst = (unsigned char*)dst;
141    unsigned char *csrc = (unsigned char*)src;
142
143    while (size--) 
144    {
145        *cdst++ = *csrc++;
146    }
147    return _dst;
148}
149
150//////////////////////////////////////////////////////////
151inline void * memset(void * dst, int s, unsigned int size) 
152{
153    char * a = (char *) dst;
154    while (size--)
155    {
156        *a++ = (char)s;
157    }
158    return dst;
159}
160
161
162//////////////////////////////////////////
163static int xprintf( char         * string,
164                    unsigned int   length,
165                    const char   * format, 
166                    va_list      * args ) 
167{
168    unsigned int ps = 0;    // write pointer to the string buffer
169
170#define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
171
172xprintf_text:
173
174    while ( *format != 0 ) 
175    {
176
177        if (*format == '%')   // copy argument to string
178        {
179            format++;
180            goto xprintf_arguments;
181        }
182        else                  // copy one char to string
183        {
184            TO_STREAM( *format );
185            format++;
186        }
187    }
188
189    return ps;
190
191xprintf_arguments:
192
193    {
194        char              buf[30];    // buffer to display one number
195        char *            pbuf;       // pointer on first char to display
196        unsigned int      len = 0;    // number of char to display
197        static const char HexaTab[] = "0123456789ABCDEF";
198        unsigned int      i;
199       
200        // Ignore fields width and precision
201        for ( ; (*format >= '0' && *format <= '9') || (*format == '.') ; format++ );
202
203        switch (*format) 
204        {
205            case ('c'):             // char conversion
206            {
207                int val = va_arg( *args, int );
208                buf[0] = val;
209                pbuf   = buf;
210                len    = 1;
211                break;
212            }
213            case ('d'):             // decimal signed integer
214            {
215                int val = va_arg( *args, int );
216                if (val < 0) 
217                {
218                    TO_STREAM( '-' );
219                    val = -val;
220                }
221                for(i = 0; i < 10; i++) 
222                {
223
224                    buf[9 - i] = HexaTab[val % 10];
225                    if (!(val /= 10)) break;
226                }
227                len =  i + 1;
228                pbuf = &buf[9 - i];
229                break;
230            }
231            case ('u'):             // decimal unsigned integer
232            {
233                unsigned int val = va_arg( *args, unsigned int );
234                for(i = 0; i < 10; i++) 
235                {
236                    buf[9 - i] = HexaTab[val % 10];
237                    if (!(val /= 10)) break;
238                }
239                len =  i + 1;
240                pbuf = &buf[9 - i];
241                break;
242            }
243            case ('x'):             // 32 bits hexadecimal
244            case ('l'):             // 64 bits hexadecimal
245            {
246                unsigned int       imax;
247                unsigned long long val;
248               
249                if ( *format == 'l' )   // 64 bits
250                {
251                    val = va_arg( *args, unsigned long long);
252                    imax = 16;
253                }
254                else                    // 32 bits
255                {
256                    val = va_arg( *args, unsigned int);
257                    imax = 8;
258                }
259               
260                TO_STREAM( '0' );
261                TO_STREAM( 'x' );
262               
263                for(i = 0; i < imax; i++) 
264                {
265                    buf[(imax-1) - i] = HexaTab[val % 16];
266                    if (!(val /= 16))  break;
267                }
268                len =  i + 1;
269                pbuf = &buf[(imax-1) - i];
270                break;
271            }
272            case ('s'):             /* string */
273            {
274                char* str = va_arg( *args, char* );
275                while (str[len]) { len++; }
276                pbuf = str;
277                break;
278            }
279/*
280            case ('f'):             // IEEE754 64 bits
281                                    // integer part : up to 10 decimal digits
282                                    // decimal part : 9 decimal digits
283            {
284                union
285                {
286                    double d;
287                    unsigned long long ull;
288                } val;
289               
290                val.d = va_arg( *args, double );
291               
292                unsigned long long mantisse;
293                mantisse = val.ull & 0xFFFFFFFFFFFFFULL;    // mantisse
294               
295                unsigned int exp;
296                exp = (unsigned int)((val.ull & 0x7FF0000000000000ULL) >> 52); // exp
297
298                if (exp == 0x7FF) // special values
299                {
300                    if (mantisse & 0xFFFFFFFFFFFFFULL)  // Not a Number
301                    {
302                        buf[0] = 'N';
303                        buf[1] = 'a';
304                        buf[2] = 'N';
305                        len = 3;
306                        pbuf = buf;
307                    }
308                    else                              // infinite
309                    {
310                        // inf
311                        buf[0] = (val.ull & 0x8000000000000000ULL) ? '-' : '+';
312                        buf[1] = 'i';
313                        buf[2] = 'n';
314                        buf[3] = 'f';
315                        len = 4;
316                        pbuf = buf;
317                    }
318                    break;
319                }
320
321                // display sign & analyse overflow
322                unsigned int overflow = 0;
323                if (val.ull & 0x8000000000000000ULL)  // negative
324                {
325                    TO_STREAM( '-' );
326                    val.d = val.d * -1;
327                    if( val.d < -9999999999.0) overflow = 1;
328                }
329                else                                  // positive
330                {
331                    TO_STREAM( '+' );
332                    if( val.d > 9999999999.0) overflow = 1;
333                }
334               
335                // check overflow caused by the 10.9 format
336                if ( overflow )   
337                {
338                    buf[0] = 'o';
339                    buf[1] = 'v';
340                    buf[2] = 'r';
341                    len = 3;
342                    pbuf = buf;
343                    break;
344                }
345
346                // compute integer & decimal parts
347                unsigned int intp;                  // integer part
348                unsigned int decp;                  // decimal part
349                intp = (unsigned int)val.d;     
350                val.d -= (double)intp;
351                decp = (unsigned int)(val.d * 1000000000);
352               
353                // display decimal value in 10.9 format
354                for(i = 0; i < 10; i++)
355                {
356                    buf[9 - i] = HexaTab[intp % 10];
357                    if (!(intp /= 10)) break;
358                }
359                pbuf = &buf[9 - i];
360                len = i+11;
361                buf[10] = '.';
362                for(i = 0; i < 9; i++)
363                {
364                    buf[19 - i] = HexaTab[decp % 10];
365                    decp /= 10;
366                }
367                break;
368            }
369*/                   
370            default:       // unsupported argument type
371            {
372                return -1;
373            }
374        }  // end switch on  argument type
375
376        format++;
377
378        // copy argument to string
379        for( i = 0 ; i < len ; i++ )
380        {
381            TO_STREAM( pbuf[i] );
382        }
383       
384        goto xprintf_text;
385    }
386} // end xprintf()
387
388//////////////////////////////////////
389int printf( const char * format, ... )
390{
391    char      string[4096];
392    va_list   args;
393    int       count;
394   
395    va_start( args, format );
396    count = xprintf( string , 4095 , format , &args ); 
397    va_end( args );
398
399    if ( count == -1 ) 
400    {
401        display_string( "stdlib : xprintf failure" );
402        return -1;
403    }
404    else 
405    {
406        string[count] = 0;
407        return write( 1 , &string , count + 1 );
408    }
409}
410
411/////////////
412int getchar()
413{
414    char byte;
415
416    if ( read( 0 , &byte , 1 ) != 1 ) return 0;
417    else                              return (int)byte; 
418}
419
420////////////////////
421int putchar( int c )
422{
423    char byte = (char)c;
424
425    if( write( 1 , &byte , 1 ) != 1 ) return 0;
426    else                              return c; 
427}
428
429////////////
430int getint()
431{
432    unsigned int  i;
433    int           val;    // ASCII character value
434
435    unsigned char buf[32];
436    unsigned int  save          = 0;
437    unsigned int  dec           = 0;
438    unsigned int  done          = 0;
439    unsigned int  overflow      = 0;
440    unsigned int  length        = 0;
441 
442    // get characters
443    while (done == 0) 
444    {
445        // read one character
446        val = getchar();
447
448        // analyse character
449        if ((val > 0x2F) && (val < 0x3A))         // decimal character
450        {
451            buf[length] = (unsigned char)val;
452            length++;                     
453            putchar( val );                       // echo
454        }
455        else if (val == 0x0A)                     // LF character
456        {
457            done = 1;
458        }
459        else if ( (val == 0x7F) ||                // DEL character
460                  (val == 0x08) )                 // BS  character
461        {
462            if ( length > 0 ) 
463            {
464                length--;         
465                printf("\b \b");                  // BS /  / BS
466            }
467        }
468        else if ( val == 0 )                      // EOF
469        {
470            return -1;
471        }
472
473        // test buffer overflow
474        if ( length >= 32 ) 
475        {
476            overflow = 1;
477            done     = 1;
478        }
479    }  // end while characters
480
481    // string to int conversion with overflow detection
482    if ( overflow == 0 )
483    {
484        for (i = 0; (i < length) && (overflow == 0) ; i++) 
485        {
486            dec = dec * 10 + (buf[i] - 0x30);
487            if (dec < save)  overflow = 1; 
488            save = dec;
489        }
490    } 
491
492    // final evaluation
493    if ( overflow == 0 )
494    {
495        // return value
496        return dec;
497    }
498    else
499    {
500        // cancel all echo characters
501        for (i = 0; i < length ; i++) 
502        {
503            printf("\b \b");                  // BS /  / BS
504        }
505
506        // echo character '0'
507        putchar( '0' );
508
509        // return 0 value
510        return 0;
511    }
512}  // end getint()
513
514///////////////////////////////////////
515int snprintf( char           * string,
516              unsigned int     length,
517              const char     * format, ... )
518{
519    va_list   args;
520    int       count;
521
522    va_start( args, format );
523    count = xprintf( string , length , format , &args ); 
524    va_end( args );
525
526    if( count < length ) string[count] = 0;
527
528    return count;
529}
530
531//////////
532int rand()
533{
534    unsigned long long cycle;
535
536    get_cycle( &cycle );
537
538    unsigned int x = (unsigned int)cycle;
539
540    if ((x & 0xF) > 7) 
541    {
542        return (x*x & 0xFFFF);
543    }
544    else 
545    {
546        return (x*x*x & 0xFFFF);
547    }
548}
549
550///////////////////////////////
551void srand( unsigned int seed )
552{
553    printf("\n[ERROR] in %s : not implemented yet : do nothing\n", __FUNCTION__ );
554}
Note: See TracBrowser for help on using the repository browser.