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

Last change on this file since 455 was 445, checked in by alain, 6 years ago

Restructure the mini_libc.

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