source: trunk/libs/mini-libc/stdio.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 9.2 KB
Line 
1/*
2 * stdio.c - User side system calls 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 <unistd.h>
27#include <almos-mkh.h>
28//////////////////////////////////////////
29static int xprintf( char         * string,
30                    unsigned int   length,
31                    const char   * format, 
32                    va_list      * args ) 
33{
34    unsigned int ps = 0;    // write index to the string buffer
35
36#define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
37
38xprintf_text:
39
40    while ( *format != 0 ) 
41    {
42
43        if (*format == '%')   // copy argument to string
44        {
45            format++;
46            goto xprintf_arguments;
47        }
48        else                  // copy one char to string
49        {
50            TO_STREAM( *format );
51            format++;
52        }
53    }
54
55    return ps;
56
57xprintf_arguments:
58
59    {
60        char              buf[30];    // buffer to display one number
61        char *            pbuf;       // pointer on first char to display
62        unsigned int      len = 0;    // number of char to display
63        static const char HexaTab[] = "0123456789ABCDEF";
64        unsigned int      i;
65       
66        // Ignore fields width and precision
67        for ( ; (*format >= '0' && *format <= '9') || (*format == '.') ; format++ );
68
69        switch (*format) 
70        {
71            case ('c'):             // char conversion
72            {
73                int val = va_arg( *args, int );
74                buf[0] = val;
75                pbuf   = buf;
76                len    = 1;
77                break;
78            }
79            case ('d'):             // decimal signed integer
80            {
81                int val = va_arg( *args, int );
82                if (val < 0) 
83                {
84                    TO_STREAM( '-' );
85                    val = -val;
86                }
87                for(i = 0; i < 10; i++) 
88                {
89
90                    buf[9 - i] = HexaTab[val % 10];
91                    if (!(val /= 10)) break;
92                }
93                len =  i + 1;
94                pbuf = &buf[9 - i];
95                break;
96            }
97            case ('u'):             // decimal unsigned integer
98            {
99                unsigned int val = va_arg( *args, unsigned int );
100                for(i = 0; i < 10; i++) 
101                {
102                    buf[9 - i] = HexaTab[val % 10];
103                    if (!(val /= 10)) break;
104                }
105                len =  i + 1;
106                pbuf = &buf[9 - i];
107                break;
108            }
109            case ('x'):             // 32 bits hexadecimal
110            case ('l'):             // 64 bits hexadecimal
111            {
112                unsigned int       imax;
113                unsigned long long val;
114               
115                if ( *format == 'l' )   // 64 bits
116                {
117                    val = va_arg( *args, unsigned long long);
118                    imax = 16;
119                }
120                else                    // 32 bits
121                {
122                    val = va_arg( *args, unsigned int);
123                    imax = 8;
124                }
125               
126                TO_STREAM( '0' );
127                TO_STREAM( 'x' );
128               
129                for(i = 0; i < imax; i++) 
130                {
131                    buf[(imax-1) - i] = HexaTab[val % 16];
132                    if (!(val /= 16))  break;
133                }
134                len =  i + 1;
135                pbuf = &buf[(imax-1) - i];
136                break;
137            }
138            case ('s'):             /* string */
139            {
140                char* str = va_arg( *args, char* );
141                while (str[len]) { len++; }
142                pbuf = str;
143                break;
144            }
145/*
146            case ('f'):             // IEEE754 64 bits
147                                    // integer part : up to 10 decimal digits
148                                    // decimal part : 9 decimal digits
149            {
150                union
151                {
152                    double d;
153                    unsigned long long ull;
154                } val;
155               
156                val.d = va_arg( *args, double );
157               
158                unsigned long long mantisse;
159                mantisse = val.ull & 0xFFFFFFFFFFFFFULL;    // mantisse
160               
161                unsigned int exp;
162                exp = (unsigned int)((val.ull & 0x7FF0000000000000ULL) >> 52); // exp
163
164                if (exp == 0x7FF) // special values
165                {
166                    if (mantisse & 0xFFFFFFFFFFFFFULL)  // Not a Number
167                    {
168                        buf[0] = 'N';
169                        buf[1] = 'a';
170                        buf[2] = 'N';
171                        len = 3;
172                        pbuf = buf;
173                    }
174                    else                              // infinite
175                    {
176                        // inf
177                        buf[0] = (val.ull & 0x8000000000000000ULL) ? '-' : '+';
178                        buf[1] = 'i';
179                        buf[2] = 'n';
180                        buf[3] = 'f';
181                        len = 4;
182                        pbuf = buf;
183                    }
184                    break;
185                }
186
187                // display sign & analyse overflow
188                unsigned int overflow = 0;
189                if (val.ull & 0x8000000000000000ULL)  // negative
190                {
191                    TO_STREAM( '-' );
192                    val.d = val.d * -1;
193                    if( val.d < -9999999999.0) overflow = 1;
194                }
195                else                                  // positive
196                {
197                    TO_STREAM( '+' );
198                    if( val.d > 9999999999.0) overflow = 1;
199                }
200               
201                // check overflow caused by the 10.9 format
202                if ( overflow )   
203                {
204                    buf[0] = 'o';
205                    buf[1] = 'v';
206                    buf[2] = 'r';
207                    len = 3;
208                    pbuf = buf;
209                    break;
210                }
211
212                // compute integer & decimal parts
213                unsigned int intp;                  // integer part
214                unsigned int decp;                  // decimal part
215                intp = (unsigned int)val.d;     
216                val.d -= (double)intp;
217                decp = (unsigned int)(val.d * 1000000000);
218               
219                // display decimal value in 10.9 format
220                for(i = 0; i < 10; i++)
221                {
222                    buf[9 - i] = HexaTab[intp % 10];
223                    if (!(intp /= 10)) break;
224                }
225                pbuf = &buf[9 - i];
226                len = i+11;
227                buf[10] = '.';
228                for(i = 0; i < 9; i++)
229                {
230                    buf[19 - i] = HexaTab[decp % 10];
231                    decp /= 10;
232                }
233                break;
234            }
235*/                   
236            default:       // unsupported argument type
237            {
238                return -1;
239            }
240        }  // end switch on  argument type
241
242        format++;
243
244        // copy argument to string
245        for( i = 0 ; i < len ; i++ )
246        {
247            TO_STREAM( pbuf[i] );
248        }
249       
250        goto xprintf_text;
251    }
252} // end xprintf()
253
254//////////////////////////////////////
255int printf( const char * format, ... )
256{
257    char      string[4096];
258    va_list   args;
259    int       count;
260   
261    va_start( args, format );
262    count = xprintf( string , 4095 , format , &args ); 
263    va_end( args );
264
265    if ( count == -1 ) 
266    {
267        display_string( "stdlib : xprintf failure" );
268        return -1;
269    }
270    else 
271    {
272        string[count] = 0;
273        return write( 1 , &string , count + 1 );
274    }
275}
276
277/////////////
278int getchar()
279{
280    char byte;
281
282    if ( read( 0 , &byte , 1 ) != 1 ) return 0;
283    else                              return (int)byte; 
284}
285
286////////////////////
287int putchar( int c )
288{
289    char byte = (char)c;
290
291    if( write( 1 , &byte , 1 ) != 1 ) return 0;
292    else                              return c; 
293}
294
295///////////////////////////////////////
296int snprintf( char           * string,
297              unsigned int     length,
298              const char     * format, ... )
299{
300    va_list   args;
301    int       count;
302
303    va_start( args, format );
304    count = xprintf( string , length , format , &args ); 
305    va_end( args );
306
307    if( count < length ) string[count] = 0;
308
309    return count;
310}
311
312
313
314
315
Note: See TracBrowser for help on using the repository browser.