source: trunk/libs/stdlib.c @ 419

Last change on this file since 419 was 416, checked in by alain, 5 years ago

Improve sys_exec.

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