Ignore:
Timestamp:
Feb 3, 2016, 9:57:40 AM (8 years ago)
Author:
alain
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_libs/stdlib.c

    r647 r771  
    77
    88#include <stdlib.h>
     9#include <stdio.h>
     10#include <stdarg.h>
    911
    1012/////////////////////////
     
    147149}
    148150
     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}
    149408// Local Variables:
    150409// tab-width: 4
Note: See TracChangeset for help on using the changeset viewer.